(Assuming .NET; similar things would apply for other platforms.)
Well, there are lots of things to consider. I'd advise:
- Immutability is great for multi-threading. Functional programming works well concurrently partly due to the emphasis on immutability.
- Use locks when you access mutable shared data, both for reads and writes.
- Don't try to go lock-free unless you really have to. Locks are expensive, but rarely the bottleneck.
Monitor.Wait
should almost always be part of a condition loop, waiting for a condition to become true and waiting again if it's not.
- Try to avoid holding locks for longer than you need to.
- If you ever need to acquire two locks at once, document the ordering thoroughly and make sure you always use the same order.
- Document the thread-safety of your types. Most types don't need to be thread-safe, they just need to not be thread hostile (i.e. "you can use them from multiple threads, but it's your responsibility to take out locks if you want to share them)
- Don't access the UI (except in documented thread-safe ways) from a non-UI thread. In Windows Forms, use Control.Invoke/BeginInvoke
That's off the top of my head - I probably think of more if this is useful to you, but I'll stop there in case it's not.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…