I attended the Concurrent Multi-Core programming pre con session by Joe Duffy, Stephen Toub and David Callahan. It was a very interesting session, with David providing an overview of the problem and the Steven and Joe sharing the presentation responsibilities for the rest of the day.
A couple of themes came out in the talk, being that scalable parallel programs will continue to see improvements, but single threaded software will not. Microsoft is moving away from a thread based model and more towards a task based model. Tasks are a more generic term for a unit of work which is more closely aligned with the problem domain. Another focus is on scalable data structures.
Stephen Toub presented on current ways to do concurrent programming in .NET using the existing frameworks.
- System.Threading.Thread
- System.Threading.ThreadPool
- Asynchronous delegate invocation
- Asynchronous Programming Model
An interesting item of note that using the ThreadPool to execute a delegate was faster than asynchronous delegate invocation, as the delegate invocation involves the remoting stack and then ends up using the ThreadPool anyway.
Manual thread management (calling Thread.Interupt, Thread.Abort, Thread.Pause & Thread.Resume) was extremely discouraged. So much so, there was talk about these APIs being deprecated in a future version of the CLR.
- Interupt only interupts a thread in a wait/sleep or join cycle. Calling this method will throw a ThreadInterruptException
- Abort will abort a thread at any moment (except during PInvoke) and will throw a ThreadAbortException. This exception is special cased by the runtime to rethrow this exception if you have caught it.
- Suspend/Resume will suspend the thread at any point, including inside a lock.
In .NET, when you lock on an object, information is stored in the available memory associated with the object. The reason this is interesting is because this additional memory allows the CLR to take a ‘slim’ lock rather than a ‘fat’ lock. However, if you call GetHashCode on this object (unless you have overridden the base implementation), this memory is used to store hash code information, and any locks on this object will be ‘fat’ locks.
Another interesting item is that items marked ThreadStatic will only be run once (not once per thread as you might assume). What this means is that if thread 1 loads up a class with a static field marked as ThreadStatic, it will have the expected value. If thread 2 then loads up this class, the static field will be null.
Joe Duffy gave a very low level talk on concurrency and shared state. It was an extremely interesting talk, about a quarter of which I was able to follow with my brain melting :(. An great example highlighted that on an x86 machine, setting an int64 value is not an atomic operation, and it’s possible for the value to be half set when the thread switches out. Compilers are free to re-order and inline statements, so you might get what you’ve asked for, but not what you’re written, which can have an impact if you’re sharing state across threads.
Synchronization best practices (Stephen Toub)
- Lock consistently
- Do lock over all mutable shared state
- Do Always use the same lock for the same state
- Do comment on how state is protected
- Lock for the right duration
- Do lock over the entire invariant
- Don’t lock for longer than is absolutely necessary
- Make critical regions short and sweet
- Do minimize the time you hold on to a lock
- Don’t call other’s code while you hold lock
- Don’t block while you hold lock
- Encapsulate your locks
- Don’t use public lock objects
- Don’t lock on Types or Strings
- Avoiding deadlocks
- Do acquire locks in a consistent order
- Locking Misceallany
- Do document your locking policy (especially for public APIs)
- Do use a reader/writer lock if readers are common
- Do prefer lock based code to lock free code
- Do prefer monitors over kernel synchronization
- Avoid lock recursion in your design
- Don’t build your own locks
- Avoid writing your own thread pool
So what’s coming in .NET 4.0?
- No real surprise, PLINQ and the Task Parallel Library (currently available in the Parallel Extensions CTP) will be included.
- A Concurrency Runtime, consisting of an improved ThreadPool with a work stealing algorith, A new task scheduler and a resource manager.
- Improved tooling support with parallel debugger windows and profiler concurrency analysis.
- Data structures such as thread safe collections ConcurrentStack<T>, ConcurrentQueue<T> and ConcurrentDictionary<K,V>. Work exchange structures such as BlockingCollection<T> and new locks such as ManualResetEventSlim<T> and SemaphoneSlim<T>.
Concurrent Programming on Windows by Joe Duffy
It looks like the trend continues, I managed to win something by sticking my hands up and answering a quiz question :) I scored the first copy to be given away of Joe Duffy’s new Concurrent Programming book. This adds to the impressive list of list of things I’ve won at nerd events.
Tags: pdc2008