I hava a class:
public class LockTest
{
public void LockThis()
{
lock (this)
{
Console.WriteLine("lock this test");
System.Threading.Thread.Sleep(5000);
}
}
}
in Main:
static void Main(string[] args)
{
LockTest lockTest = new LockTest();
lock (lockTest)
{
//lockTest.LockThis();
System.Threading.Thread thread = new Thread(lockTest.LockThis);
thread.Start();
}
Console.Read();
}
I thought the invoking lockTest.LockThis() will cause a dead lock but it didn't. I don't konw why.
The explanation here is timing.
The code in Main that starts the thread manages to escape the lock before the thread has fully started and gotten to the point where it too will try to take the lock.
Try moving the Console.Read line into the lock block, and you'll see what I mean.
Also note that even if the thread managed to reach the locking code before the Main method has escaped the lock, it will simply wait for that to happen (wait for the main thread to escape the lock), and then continue onwards.
So there is no deadlock here, at all.
A deadlock is when two threads wait for each other, or something similar. You don't have that in this code.
There can be no deadlock in this code.
When the thread LockThis starts, the lock is owned by the main thread, so it starts and then it goes on wait. The main thread continues and exits the lock (the line before the Console.Read). At this time the LockThis thread can continue. No deadlock.
Main Thread LockThis
lock (not started)
start LockThis
try lock, failure, goes in wait
unlock
Console.Read()
awakened because the lock is free
lock
unlock
Another scenario: the main thread starts the LockThis thread. The main thread then continues and exits the lock before the LockThis thread has even begun working, so before it tries to enter the lock. Even in this scenario there is no deadlock.
Main Thread LockThis
lock (not started)
start LockThis
unlock
lock
Console.Read()
unlock
(note that in both cases, the position of the unlock in LockThis is irrelevant. You can move it up or down)
If you look at the wiki you'll see that to have a deadlock one has to have
At least two resources must be non-shareable.
You here have only one resource (the lock (lockTest)).
You are leaving the lock(lockTest) block before the thread locks lockTest.
Related
I was going through Microsoft docs for ThreadPool and they explained that ThreadPool threads are background threads which do not keep the application running if all foreground threads have terminated.
Here is the code snippet:
public static void Main()
{
ThreadPool.QueueUserWorkItem(ThreadProc);
Console.WriteLine("From main foreground thread");
//Thread.Sleep(1000);
Console.WriteLine("Exiting from main");
}
static void ThreadProc(object stateInfo) {
Console.WriteLine("From the thread pool");
}
With Thread.Sleep(1000) uncommented it is sure that the background thread will complete before the main foreground thread exits. But when we comment the sleep part then also I get an output of sort:
From main foreground thread
Exiting from main
From the thread pool
It means that the background thread is still executed even when the main foreground thread has exited. Why so?
The end of the Main method doesn't mean the "foreground" thread has exited. Even if it has, it doesn't mean your process has terminated.
Normally, a process stops when all threads that run in the process (including the ones from the thread-pool, which have queued work) terminate. However, if you exit a process using ExitProcess. The CLR works in a slighly more complicated way (see here), which does quite some clean-up before really existing the application.
As a result, before all working threads get killed, there is pretty some time when work can get done.
In my application I use a ReaderWriterLockSlim to synchronize reads and writes from/to a list<>.
In the following example reading the list is performed inside all 3 sub-methods, thus these 3 should be packed into a ReadLock. The problem is that SubMethod3 is called via a BackgroundWorker (as it contains lengthy calculations), so the ExitReadLock() in the finally block of MainMethod1 might be called before SubMethod3 has been finished by the BackgroundWorker (separate thread). Thereby the code in SubMethod3 is not really protected by the lock.
What I have considered is to use a lock in each sub-method, so Submethod3 would have its own lock, which would be released when the BackgroundWorker was done. The problem with this approach is that another thread could enter in between the calls of the sub-methods, as each of these would release the lock when done.
My question is: How can ReadLock be used to protect over more threads?
ReaderWriterLockSlim synchronizationLock = new ReaderWriterLockSlim();
public void MainMethod1()
{
synchronizationLock.EnterReadLock();
try
{
SubMethod1(); //Run on UI thread
SubMethod2(); //Run on UI thread
myBackgroundWorker.RunWorkerAsync();
}
finally
{
synchronizationLock.ExitReadLock();
}
}
private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
SubMethod3(); //Run on separate thread
}
In general you are out of luck. Due to thread affinity, you cannot release the lock from another thread. If you try to hold the reader lock (with the idea that this will allow the worker to acquire its own read lock), and wait the worker thread to start, acquire a reader lock and notify you, so you can release the read lock at that time, all you'll get would be a deadlock if there is a waiting writer thread due to reader/waiter fairness of the ReaderWriterLock(Slim) implementation.
I see the following options:
(A) Run the whole MainMethod1 on a separate thread.
(B) Write and use your own reader/writer lock implementation that supports such scenario.
(C) Get rid of BackgroundWorker and switch to async/await implementation using one of the AsyncReaderWriterLock implementations described here ReaderWriterLockSlim and async\await
(D) Since I've noticed the comment Run on UI thread, only and only if the method is used by a thread that supports marshalling calls from another thread (which is true for WF and WPF UI threads), you can use the following technique:
public void MainMethod1()
{
synchronizationLock.EnterReadLock();
bool releaseLock = true;
try
{
SubMethod1();
SubMethod2();
RunWorkerCompletedEventHandler onRunWorkerCompleted = null;
onRunWorkerCompleted = (sender, e) =>
{
((BackgroundWorker)sender).RunWorkerCompleted -= onRunWorkerCompleted;
synchronizationLock.ExitReadLock();
};
myBackgroundWorker.RunWorkerCompleted += onRunWorkerCompleted;
myBackgroundWorker.RunWorkerAsync();
releaseLock = false;
}
finally
{
if (releaseLock)
synchronizationLock.ExitReadLock();
}
}
Please note than while option (D) seems to solve the issue in the context of MainMethod1, it can easily lead to a deadlock if the UI thread tries to acquire read lock from another place and there is a pending writer waiting.
In general working with long time hold locks from the UI thread is a bad idea that is causing more problems rather than solving something. IMO the best are the options (A) and (C), and so far (A) is the simplest if you can afford it (if SubMethod1 and SubMethod2 do not need to be run on the UI thread or can marshall the necessary calls to it).
I have question regarding threading in c#.See the code posted below.
public class TestThreading
{
private System.Object lockThis = new System.Object();
public void Function1()
{
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
public void Function2(){
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
}
Now my question is if some thread entered in Function1 (inside lock block) and at the same time another thread enters in Function2 what will happen
The threads will execute independently.
The thread which entered in Function 2 Goes to waits until lock is released by Funtion1 thread.
The thread which entered in Function 2 throws exception.
I am new to c# hence asking simple basic question.
Thanks in advance.
The thread which entered in Function 2 Goes to waits until lock is released by Funtion1 thread.
The purpose of the lock is just that: provide a "safe" region of code that can be accessed only by one thread at a time. The other thread will be put to sleep, and resumed when the first one releases the lock.
Number 2 will happen. The second thread will wait for the lock to be released before executing.
The second thread will wait for the first one to release the lock and only then it will acquire the lock and preform your code
I suggest reading the following articles which describe MultiThreading issues and libraries
Managed Threading Best Practices
Threading in C#
Joseph Albahari
In the stacktrace, MessageProcessor.Dispose(), OnThreadShutdownRequested and RenewTaskLeaseCallback all require a lock to prevent race conditions in these objects.
The stacktrace for thread (ID14968) holds all the locks, which causes the other threads to block and wait for it to release the locks.
The problem is that, when CloseConnection() is called on thread-14968, the connection is never closed, and SyncAsyncLock.Wait() was called internally inside CloseConnection(). Call is blocked and would not continue, and a deadlock situation occurs.
What would possibly cause the thread to block when CloseConnection() was called?
Larger image here.
After working on this issue for two days, I finally figured out the problem.
There was a situation that could result a deadlock in the application.
The TaskLeaseRenewer object implements IDisposable and can be accessed by multiple threads. A lock is used inside the class to make sure no two threads will try to dispose the object at the same time. TaskLeaseRenewer has a timer, and callback function Callback that will be called periodically by the timer, on a separate thread. The Callback thread will try to call Thread.Abort() on the thread that created the TaskLeaseRenewer and eventually call Dispose() on TaskLeaseRenwer
The problem happens when I try to abort the thread that does does the following:
using(TaskLeaseRenewer renewer = new TaskLeaseRewnewer())
{
DoStuff();
}
I found out that when you call Thread.Abort() on a thread with using statements, it will not terminate the thread until it call the Dispose() function on the used object.
The example below will trigger ConnectionWrapper.Dispose() before the thread is aborted.
static void DisposeOnAbort()
{
Thread t = new Thread(() =>
{
Console.WriteLine("Using connection wrapper");
using (ConnectionWrapper wrapper = new ConnectionWrapper())
{
while (true)
{
Thread.Sleep(1000);
}
}
});
t.Start();
Thread.Sleep(1000);
Console.WriteLine("Aborting thread..");
t.Abort();
}
Given these, I found the problem is when Callback() calls Thread.Abort(), TaskLeaseRenewer.Dispose() will be called on the thread it was created because the thread is getting ready to be killed. However Callback() function is on a different thread and also holding the lock the Dispose() function is trying to acquire. Dispose() will not be able to acquire the lock, and the thread will never terminate.
After solving this problem, the connection.Close() deadlock seems to be gone. I am still interested in what could be blocking the connection from closing.
After playing around with this problem more, i find when a thread is aborted, the disposable object's Dispose() object is always called. whether using statement is used or not. Callstack as follows:
Threads.exe!Threads.ConnectionWrapper.Dispose() Line 150 C#
Threads.exe!Threads.Program.DisposeOnAbort.AnonymousMethod__0() Line 58 + 0x2c bytes C#
I have two methods, MethodA & MethodB. MethodB has to run on the UI thread. I need them to run one after the other without allowing MethodC to run between them.
MethodC is called when a user clicks on a lovely little button.
What I did to ensure this is put a Lock around the code thus:
lock (MyLock)
{
MethodA(param1, param2);
MyDelegate del = new MyDelegate(MethodB);
if (this.IsHandleCreated) this.Invoke(del);
}
And for MethodC:
public void MethodC()
lock (MyLock)
{
Do bewildering stuff.....
}
Problem is I'm getting stuck. It looks like my code's going into a deadlock.
When I look at the threads I see that the code called by the button click is stuck at lock (MyLock) in MethodC and my other thread seems stuck at this.Invoke(del).
I've read it's dangerous to invoke a method from within a Lock but since I'm the one who wrote the code there and this seems to happen even with just a Thread.Sleep I figure it's not the code that's getting me into trouble.
Why would the the Invoked method stop working?
Is it possibly waiting for the lock on methodC to be released before going back to the original lock it was invoked from?
So, imagine the following situation:
Your background thread starts running the code. It grabs the lock and then starts running MethodA.
MethodC is called while MethodA is in the middle of its work. MethodA waits for the lock to be free, blocking the UI thread until that happens.
The background thread finishes MethodA and goes to invoke MethodB on the UI thread. MethodB can't run until all previous items in the message pump's queue have finished.
MethodC is at the top of the message pump's queue, waiting until MethodB finishes, and MethodB is in the queue waiting until MethodC finishes. They are both waiting on each other, which is a deadlock.
So, how do you resolve this issue? What you really need is some way of "waiting" on a lock without actually blocking the thread. Fortunately (in .NET 4.5) this is easy to do thanks to the Task Parallel Library. (I have waiting in quotes because we don't actually want to wait, we just want to execute MethodC as soon as the lock is freed without actually waiting/blocking the current thread.)
Instead of using an object for MyLock use:
private static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
Now for MethodC you can do:
public async Task MethodC() //you can change the signature to return `void` if this is an event handler
{
try
{
await semaphore.WaitAsync();
//Do stuff
}
finally
{
semaphore.Release();
}
}
The key here is that because we await a task that represents when the semaphore is actually free we aren't blocking the current thread, which will allow the other background task to marshal MethodB to the UI thread, finish the method, release the semaphore, and then let this method execute.
Your other code doesn't need to (but still can, if you want) use async waiting on the semaphore; blocking the background thread isn't nearly as much of a problem, so the only key change there is using the semaphore instead of lock:
public void Bar()
{
try
{
semaphore.Wait();
MethodA(param1, param2);
MyDelegate del = new MyDelegate(MethodB);
if (this.IsHandleCreated) this.Invoke(del);
}
finally
{
semaphore.Release();
}
}
Assuming your MethodA also contains something like:
lock(MyLock) {
}
You are absolutely correct, you've got a dead lock. MethodA cannot obtain a lock on MyLock because it was already locked before the method was entered.
You can rather try this:
Lock (MyLock)
{
MethodA(param1, param2);
MyDelegate del = new MyDelegate(MethodB);
MyDelegate del2 = new MyDelegate(MethodC);
MyDelegate del3 = del+del2
if (this.IsHandleCreated) this.Invoke(del3);
}
You confused a hell out of people using lock. This task has nothing to do with multi-threading per se.
Simple usability solution is what you need - disable your lovely little button until you are ready to run MethodC.