使用锁的最佳实践

Bel*_*oda 9 c# locking

假设我在某个类中有以下属性,其目的是用作锁.

protected object SyncRoot { get; private set; }
Run Code Online (Sandbox Code Playgroud)

无论如何,无论如何以及如何设置.如果它实际上是设置的话,最好的做法是什么?

由于lock不能与null对象一起使用,我应该像这样处理吗?

lock (SyncRoot ?? new object())
    SomeMethod();
Run Code Online (Sandbox Code Playgroud)

或者我应该像这样检查null吗?

if (SyncRoot != null)
    lock (SyncRoot)
        SomeMethod();
else
    SomeMethod();
Run Code Online (Sandbox Code Playgroud)

事实上,如果设置它,我想用它来锁定.否则,我不在乎.无论如何,第一个解决方案效率低下还是多余?

编辑:所有这些答案都很好.但是,我只能选一个.鉴于我与Luke讨论的情况,我的SyncRoot没有理由为null.单线程环境中锁的开销不是很大,但如果是多线程的,则是必需的.

(投票给所有4个人)感谢大家的快速回复.

Not*_*ple 21

我通常使用私有成员变量而不是属性,即

private static object MyLock = new object();
Run Code Online (Sandbox Code Playgroud)

这种方式总是初始化.

您还可以使用非静态版本,例如

private readonly object MyLock = new object();
Run Code Online (Sandbox Code Playgroud)


das*_*ght 13

同步

SyncRoot ?? new object()
Run Code Online (Sandbox Code Playgroud)

没有意义,因为如果SyncRootnull,每个线程每次都会获得一个新对象.在单独的对象上同步没有任何效果:线程将立即继续,因为没有其他人可能在同一new对象上同步.

您应该SyncRoot在第一个线程尝试获取锁之前在构造函数中初始化.

  • @Beljoda,在“ new object()”上进行同步的性能影响不大,因为它是完全没有用的习语。 (2认同)
  • 速度无所谓; 如果每个通过您的代码的线程都创建一个新的锁对象,那么您的代码就不会受到访问受保护资源的多个线程的保护.要让线程一次排队并访问受保护资源,他们必须全部锁定SAME对象实例. (2认同)