gho*_*ago 16 .net c# multithreading locking thread-safety
我有一个类似的方法:
public static void DoSomething (string param1, string param2, SomeObject o)
{
//.....
lock(o)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
Run Code Online (Sandbox Code Playgroud)
几点:
private static object
吗? Hei*_*nzi 21
为了最大限度地减少副作用,被锁定的对象不应该是被操纵的对象,而应该是指定用于锁定的单独对象.
根据您的要求,有几个选项可以解决此问题:
变体A:私人锁定对象
如果您只想确保DoSomething
不与并行实例冲突,请选择此选项DoSomething
.
private static readonly object doSomethingLock = new object();
public static void DoSomething (string param1, string param2, SomeObject o)
{
//.....
lock(doSomethingLock)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
Run Code Online (Sandbox Code Playgroud)
变体B:将锁定对象作为参数传递
如果访问o
必须是线程安全的,即使在外部DoSomething
,即,如果有可能存在其他人编写DoSomethingElse
并行运行DoSomething
且不得干扰该lock
块的方法的情况,请选择此选项DoSomething
:
public static void DoSomething (string param1, string param2, SomeObject o, object someObjectLock)
{
//.....
lock(someObjectLock)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
Run Code Online (Sandbox Code Playgroud)
变体C:创建SyncRoot属性
如果您可以控制实现SomeObject
,则可以方便地将锁定对象作为属性提供.这样,您可以实现Variant B而无需传递第二个参数:
class SomeObject
{
private readonly object syncRoot = new object();
public object SyncRoot { get { return syncRoot; } }
...
}
Run Code Online (Sandbox Code Playgroud)
然后,您只需使用lock(o.SyncRoot)
在DoSomething
.这是一些BCL类使用的模式,例如,Array.SyncLock,ICollection.SyncRoot.