So you are into thread safe code and you have begun to lock resources. The trap that all new programmersis to lock the whole class. Just as shown below:
public void DeadlockWaitingToHappen1(string change)
{
lock (this)
{
_Resource1 = change;
}
}
public void DeadlockWaitingToHappen2(string change2)
{
lock (this)
{
_Resource2 = change2;
}
}
The problem with the above code, albeit trite due to the example, is that when a thread 1 calls the first method to change resource1, it will effectively block any other thread calling the opposite method to change _resource2.
Because we know that these resources are independent, such locking in the above case is a nuance, in a more advanced state, causes undo wait times for resources, but in a worse case scenario could cause deadlocks in code!
Solution
To get around that what we will do is to lock separate objects. The below code will create mirror object locks and use those to properly lock our different distinct resources.
// This class simulates the use of two different
// thread safe resources and how to lock them
// for thread safety but not block other
// threads getting different resources.
public class SmartLocking
{
private string _Resource1;
private string _Resource2;
private object _Lock1 = new object();
private object _Lock2 = new object();
public void DoWorkOn1(string change)
{
lock (_Lock1)
{
_Resource1 = change;
}
}
public void DoWorkOn2(string change2)
{
lock (_Lock2)
{
_Resource2 = change2;
}
}
}
As you can see we have separate locks, so now thread 1 accessing resource 1 won’t block thread 2 accessing resource 2. Note if the object you are working contains the interface to allow locking and it makes sense to use that resource, then lock it instead of a separate object.
Pingback: DevTopics | Best C# Blogs
#1 by Greg Beech on April 13, 2008 - 3:58 pm
Quote
Actually that couldn’t cause a deadlock because there is only a single lock taken. You’re right that it could cause more contention than is strictly necessary, but for a deadlock you need two locks taken in different orders. Below is an example of a deadlock waiting to happen:
class DeadlockWaiting
{
readonly object lock1 = new object();
readonly object lock2 = new object();
public void DoWork1()
{
lock (lock1)
lock (lock2)
// synchronised code
}
public void DoWork2()
{
lock (lock2)
lock (lock1)
// synchronised code
}
}
Here it is possible for DoWork1 to lock lock1, and DoWork2 to lock lock2, and then each method is waiting for the other to release the lock (which will never happen) hence the deadlock.
If there is only one lock, then it will always be released, hence no deadlock.
Pingback: Лучшие C# блоги и не только… « Блог Серёжи Борзова
#2 by Russ on September 19, 2008 - 8:28 am
Quote
Why not just lock on _Resource1 and _Resource2 instead of creating separate objects. Its cleaner and does the same thing, no?
#3 by omegaman on September 19, 2008 - 8:50 am
Quote
Yes locking the actual object is cleaner in most cases. This article is targeted to developers who lock the whole object (lock(this)). They may not know that one can lock *other* objects or the objects themselves. Thanks for the thought!
Pingback: GoTinker » Locking and multi-threading