我的方法类似于:
public static void DoSomething (string param1, string param2, SomeObject o)
{
//.....
lock(o)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
几点:
private static object
吗? 答案 0 :(得分:20)
为了最大限度地减少副作用,被锁定的对象不应该是被操纵的对象,而应该是指定用于锁定的单独对象。
根据您的要求,有几个选项可以解决此问题:
变体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....
}
}
变式B:将锁定对象作为参数传递
如果o
的访问权限即使在DoSomething
之外也必须是线程安全的,即,如果其他人编写与DoSomethingElse
并行运行的方法DoSomething
,则选择此项{1}}并且不得干扰lock
中的DoSomething
阻止:
public static void DoSomething (string param1, string param2, SomeObject o, object someObjectLock)
{
//.....
lock(someObjectLock)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
变体C:创建SyncRoot属性
如果您可以控制SomeObject
的实现,则可以方便地将锁定对象作为属性提供。这样,您可以实现Variant B而无需传递第二个参数:
class SomeObject
{
private readonly object syncRoot = new object();
public object SyncRoot { get { return syncRoot; } }
...
}
然后,您只需在lock(o.SyncRoot)
中使用DoSomething
即可。这是一些BCL类使用的模式,例如Array.SyncLock,ICollection.SyncRoot。
答案 1 :(得分:2)
回答你的第3个问题:
想象一下,后者决定锁定另一个方法参数,可能是:
public void XXX(object o)
{
lock(o)
{
}
}
您将很难尝试查看是否存在死锁。您需要检查作为参数传递给SomeObject的对象o是否永远不会作为参数传递给对象o。
答案 2 :(得分:0)
以下是一个关于如何使用锁的示例:
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
这意味着您锁定一个私有变量的Object,仅用于锁定而不是其他任何东西,
你可以看看这个:
和