Some newbie questions about multi-threading in .NET which I think will help reinforce some concepts I’m trying to absorb – I’ve read several multi-threading material (including the Albahari ebook) but feel I just need some confirmation of some questions to help drive these concepts home
-
A lock scope protects a shared region of code – suppose there is a thread executing a method that increments a simple integer variable x in a loop – however this won’t protect code elsewhere that might also alter variable x eg in another method on another thread …
Since this is two different regions of code potentially affecting the same variable, do we solve this by locking both regions of code using the same lock variable for both lock scopes around variable x? If you locked both regions of code with different lock variables, this would not protect the variable correct?
-
To further this example, using the same lock variable, what would happen if for some reason, code in one method went into some infinite loop and never relinquished the lock variable – how could the second region of code in the other method detect this?
-
How does the choice of lock variable influence the behavior of the lock? I’ve read numerous posts on this subject already but can never seem to find a definitive answer – in some instances people explicitly use an object variable specifically for this purpose, other times people use lock(this) and finally there’ve been times I’ve seen people use a type object.
How do the different choices of lock variables influence the behavior / scope of the lock and what scenarios would it make sense to use one over the other?
- suppose you have a hashtable wrapped in a class exposing add, remove, get and some sort of Calculate method (say each object represents a quantity and this method sums each value) and all these methods are locked – however, once a reference to an object in that collection is made available to other code and passed around an application, this object (not the hashtable) would now be outside the lock scope surrounding the methods of that class ..how could you then protect access / updates to those actual objects taken from the hashtable, which could interfere with the Calculate method?
Appreciate any heuristics provided that would help reinforce these concepts for me – thanks!
1)
You are correct. You must use the same lock object to protect two distinct area’s of code that for example increment the variable x.
2)
This is known as a deadlock and is one of the difficulties with multithreaded programming. There are algorithms which can be used to prevent deadlocks such as the Bankers Algorithm.
3)
Some languages make locking easy, for example in .Net you can just create an object and use it as the shared lock. This is good for synchronising code within a given process. Lock(this) just applies the lock to the object in question. However try to avoid this, instead create a private object and use that. Lock(this) can lead to deadlocking situations. The lock object underneath is probably just a wrapper around a Critical Section. If you wanted to protect a resource across different processes you would need a much heavier named Mutex, this requires a lock on a kernel object and is expensive, so do not use unless you must.
4)You need to make sure locking is applied there as well. But surely when people call methods on this reference they call the methods which employ synchronisation.