问题描述
我有一个方法类似:
公共静态无效DoSomething的(字符串参数1,字符串参数2,SomeObject O)
{
// .....
锁定(O)
{
o.Things.Add(参数1);
o.Update();
// 等等....
}
}
的几点:
- 是锁定在这样不好的做法?
- 我应该锁定在
私有静态对象
呢? - 如果是这样,为什么 ?
要最大限度地减少副作用,该对象被锁定在不应该的对象被操纵,而是一个独立的对象指定为锁定。
根据您的要求,有几个选项来处理这个问题:
方案A:私人锁定对象
选择这个,如果你只是想确保的DoSomething
不与 DoSomething的一个平行的实例冲突
。
私有静态只读对象doSomethingLock =新的对象();
公共静态无效DoSomething的(字符串参数1,字符串参数2,SomeObject O)
{
// .....
锁定(doSomethingLock)
{
o.Things.Add(参数1);
o.Update();
// 等等....
}
}
方案B:通过锁定对象作为参数
如果选择此访问 0
必须是线程安全的外连的DoSomething
,即,如果可能存在别人写了一个方法 DoSomethingElse
它运行在平行于的DoSomething
并不得与<$ C干扰
的DoSomething
块 公共静态无效DoSomething的(字符串参数1,字符串参数2,SomeObject 0,对象someObjectLock)
{
// .....
锁定(someObjectLock)
{
o.Things.Add(参数1);
o.Update();
// 等等....
}
}
变通方案C:创建SyncRoot属性
如果你有超过 SomeObject
的实施控制,这可能是方便的为客户提供锁定对象的属性。通过这种方式,可以实现变式B,而不必绕过第二个参数:
类SomeObject
{
私人只读对象SyncRoot上=新的对象();
公共对象SyncRoot上{{返回SyncRoot上; }}
...
}
然后,你只需要使用锁(o.SyncRoot)
在的DoSomething
。这是一些BCL类使用模式,例如, Array.SyncLock , ICollection.SyncRoot.
I have a method similar to:
public static void DoSomething (string param1, string param2, SomeObject o)
{
//.....
lock(o)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
A few points:
- Is locking in this way bad practice?
- Should I lock on a
private static object
instead? - If so, why?
To minimize side effects, the object being locked on should not be the object being manipulated but rather a separate object designated for locking.
Depending on your requirements, there are a few options for handling this issue:
Variant A: Private locking object
Choose this if you just want to ensure that DoSomething
does not conflict with a parallel instance of 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....
}
}
Variant B: Pass locking object as a parameter
Choose this if access to o
must be thread-safe even outside of DoSomething
, i.e., if the possibility exists that someone else writes a method DoSomethingElse
which runs in parallel to DoSomething
and which must not interfere with the lock
block in DoSomething
:
public static void DoSomething (string param1, string param2, SomeObject o, object someObjectLock)
{
//.....
lock(someObjectLock)
{
o.Things.Add(param1);
o.Update();
// etc....
}
}
Variant C: Create SyncRoot property
If you have control over the implementation of SomeObject
, it might be convenient to provide the locking object as a property. That way, you can implement Variant B without having to pass around a second parameter:
class SomeObject
{
private readonly object syncRoot = new object();
public object SyncRoot { get { return syncRoot; } }
...
}
Then, you just use lock(o.SyncRoot)
in DoSomething
. That's the pattern some of the BCL classes use, e.g., Array.SyncLock, ICollection.SyncRoot.
这篇关于C#中的引用锁定传递给方法 - 不好的做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!