Reputation: 119
Can you please explain why this code deadlocks ?
int[] testlist = new int[ ] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
lock ( testlock ) {
Parallel.ForEach( testlist, new ParallelOptions( ) { MaxDegreeOfParallelism = 90 }, ( int i ) => {
Console.WriteLine( "hi there before " + i + " " + Monitor.IsEntered( testlock ) );
lock ( testlock ) {
Console.WriteLine( "hi there inner " + i + " " + Monitor.IsEntered( testlock ) );
}
Console.WriteLine( "hi there after " + i + " " + Monitor.IsEntered( testlock ) );
} );
}
Of course without the surrounding lock this code do not deadlock.
Edit:
thanks for the explanation. The typical output is:
hi there before 3 True
hi there inner 3 True
hi there after 3 True
hi there before 4 True
hi there inner 4 True
hi there after 4 True
hi there before 5 True
hi there inner 5 True
hi there after 5 True
hi there before 6 True
hi there inner 6 True
hi there after 6 True
hi there before 7 True
hi there inner 7 True
hi there after 7 True
hi there before 8 True
hi there inner 8 True
hi there after 8 True
hi there before 9 True
hi there inner 9 True
hi there after 9 True
hi there before 10 True
hi there inner 10 True
hi there after 10 True
In fact, typical execution involes two threads on my machine: one is blocked waiting for lock (the "1" one) and another is running other iterations (from 3 to 10, note the linearity of output). The "1" thread waits forever. Now it is clear, thanks !
Upvotes: 1
Views: 2124
Reputation: 141703
You have taken a lock on testLock
before starting Parallel.ForEach
(1st lock). Inside of your Parallel.ForEach, you take a lock on the same object. The ForEach uses a different thread at some point other than the one that took the 1st lock. That thread is going to wait until the lock is available, however it will never be available because the 1st lock won't get released until the ForEach is complete.
Since ForEach
won't exit until all threads are complete, you end up deadlocked.
Upvotes: 3
Reputation: 23113
This can't work because you are definitely creating a deadlock here:
The outer lock(testlock)
locks on testlock
and then the Parallel.ForEach
starts processing your testlist
in multiple threads. Now these threads get to the inner lock(testlock)
, but as it is still locked by the outer one in its thread it can not lock it again => the outer lock
does not release until the processing is done, but the processing can not complete until the outer lock
releases -> deadlock...
You can easily verify this by using MaxDegreeOfParallelism = 1
: Then everything runs in the main thread and the cascaded lock does not deadlock as it can lock again, because it is the same thread.
What are you trying to do - may we can help if you explain?
NOTE:
If your system does not have 90! CPU's it does NOT help the performance to use MaxDegreeOfParallelism = 90
- it is recommended to keep that number smaller or equal to your CPU/Core count (you can get that via Environment.ProcessorCount
).
Upvotes: 5