From Joe White’s blog, I came across a link to an interesting article about working with various locking models when writing multithreaded code. It was written by Vance Morrison, the compiler architect for the .NET Runtime and it’s required reading for anyone doing multithreaded coding. It was written a few years back, but is still relevant. I’ve read it a couple of times and I still have not grokked all of it.
The article is written for the .NET Framework 2.0, but the concepts are applicable to anyone doing multithreaded code. I agree with Joe’s assessment, if you don’t understand what Vince is talking about for any of the techniques described in the article, then don’t use that that technique. Debugging thread interactions is not easy and using a debugger will change your program flow enough to make it difficult to catch thread conflicts.
What’s good with this article is that Vince goes down to the metal and explains how the multiprocessor machines changed the game with how threads access memory. Memory access is no long serially consistent, each processor has multiple levels of cache memory and the processor will attempt to retrieve cached memory before checking system memory. Know how that works and when cache memory is synchronized back to system memory is important and can be a factor in determining what type of locking mechanism to build into your threads. This article describes situations where you can eliminate locks for locks for some types of threaded memory access. Vince refers to these techniques as “Low-Lock”.
It is important to note that using Low-Lock will make your code fragile as you are much more dependant on on how the hardware will behave in terms of memory access. They should only be used when the performance increase is absolutely required. Vince has a related article called “Concurrency: What Every Dev Must Know About Multithreaded Apps” does a very good job of explaining how to use locks properly with multithreaded code. He linked to that article in the lock lock article, but that link is broken. Use this one instead.