C# Nested Synchronization
I have a class with several data members:
public class Foo
{
List<int> intLst;
int Whatever;
HashTable<string> hshTable;
...
}
I then have a function within Foo that takes two Foos and merges them into a new Foo. I would like to make the Foo class thread safe too. Is the below code the best way to do this?
public Foo(Foo f)
{
lock(f)
{
foreach (int i in f.intLst)
{
this.intLst.Add(i)
}
//More complicated
}
}
public Foo Merge(Foo f1, Foo f2)
{
Foo fReturn = new Foo(f1);//Using the constructor above
lock(f2)
{
foreach (int i in f2.intLst)
{
fReturn.intLst.Add(i);
}
//More complicated merge code
}
return fReturn;
}
Is it that simple? Should I use Monitors instead? I know lock implements the monitor class, but is there perhaps still a reason. Also do I need to worry about handling deadlock in my above sample.
I feel like a I need to lock() both f1 and f2 because what if f2 changes during the copy constructor on 开发者_运维技巧f1?
Yes, it is that simple.
Your code is good. You don't need to lock f2 until you access it, and you don't need to lock f1 after it has been copied. So there really is no need to lock both at the same time.
In your example the items themselves are simple integers which are immutable so there is no need to lock them, but if you had mutable items you may need to lock the individual items.
You don't need to worry about deadlock with just this code since you only hold one lock at a time. Of course if some other code calls it while holding a lock you might need to worry about the possiblity of deadlock.
lock() only works on other lock() blocks. So lock(f) will block other code that is working with f as long as that code also has lock(f), so lock(f) has to be on all usages of (f).
You don't need to worry about locking the target Foo since it's still being constructed--nothing else can have a reference to it yet.
精彩评论