I've written a lot of multi-threaded C# code, and I've never had a deadlock in any code I've released.
I use the following rules of thumb:
- I tend to use nothing but the
lock
keyword (I also use other techniques such as reader/writer locks, but sparingly, and only if required for speed). - I use
Interlocked.Increment
if I am dealing with along
. - I tend to use the smallest granular unit of locking: I only tend to lock around primitive data structures such as
long
,dictionary
orlist
.
I'm wondering if it's even possible to generate a deadlock if these rules are thumb are consistently followed, and if so, what the code would look like?
Update
I also use these rules of thumb:
- Avoid adding a lock around anything that could pause indefinitely, especially I/O operations. If you absolutely have to do so, ensure that absolutely everything within the lock will time out after a set
TimeSpan
. - The objects I use for locking are always dedicated objects, e.g.
object _lockDict = new object();
thenlock(_lockDict) { // Access dictionary here }
.
Update
Great answer from Jon Skeet. It also confirms why I never get deadlocks as I tend to instinctively avoid nested locks, and even if I do use them, I've always instinctively kept the entry order consistent.
And in response to my comment on tending to use nothing but the lock
keyword, i.e. using Dictionary
+ lock
instead of ConcurrentDictionary
, Jon Skeet made this comment:
@Contango: That's exactly the approach I'd take too. I'd go for simple code with locking over "clever" lock-free code every time, until there's evidence that it's causing an issue.