为什么需要C#的锁对象?

时间:2018-06-03 21:17:51

标签: c# thread-safety locking

您有时可以将对象本身重用于锁定,但通常建议使用不同的对象。

如果只有锁定关键字,我们是否还有更多的类型安全和更好的意图?

private object _MyLock = new object();

// someone would now be able to reassign breaking everything
_MyLock = new object();

lock ( _MyLock )
    ...

VS

private lock _MyLock;

// compiler error
_MyLock = new object();

lock ( _MyLock )
    ...

在我投票之前,你无法猜到某人的意图:我很确定语言设计师有充分的理由,而且现在有更多知识渊博的编码员,为什么呢。我要求这样理解更好的编程原则。

3 个答案:

答案 0 :(得分:0)

一种解决方案可能是将锁定对象定义为readonly

static readonly object lockObject = new object();

在这种情况下,编译器会阻止续订并将新对象分配给lockobject

答案 1 :(得分:0)

请注意,通过使用对象作为监视器,您可以完成所有可以对任何其他对象执行的操作:传递引用,以便多个类可以共享同一个监视器,将它们保存在数组中,将它们保存在其他数据中结构。

如果你有一个特殊类型的可锁定声明,你需要特殊的语法将它传递给一个函数,在另一个实例中存储对它的引用,将它与一个类型而不是一个实例相关联,创建数组(例如对于LockMany操作),等等。

使用对象已经存在的语言规则来处理所有这些常见和不那么常见的用法,使语言变得更加简单。

答案 2 :(得分:0)

  

如果只有一个锁定关键字,我们还有更多的类型安全和更好的意图吗?

根本不是关于类型安全的。它涉及线程的安全性。

有时这意味着一遍又一遍地在一个lock中运行相同的代码。也许你有一个大型数组,你的某些操作可能需要交换两个元素,并且你想确保在交换期间事情是同步的。在这种情况下,即使是简单的lock关键字本身,在幕后为您创建对象,也可能足够好。

有时您会在非常不同的代码集之间共享对象。现在,您需要使用公共对象进行协调的多个lock部分。在这种情况下,您正在谈论的代码似乎有意义。让编译器为你创建一个锁定对象是不够好的,因为不同的lock部分不会协调,但你也想确保公共锁定对象是固定的,并且不会改变不知何故。例如,您可能正在使用具有多个线程的阵列,并且您可以使用不同的操作来修改共享索引值,该值指示哪个元素被视为当前或活动。这些操作中的每一个都应该锁定在同一个对象上。

但有时你会在几组代码中共享多个对象实例(通常是相同类型)。想想生产者/消费者模式,其中来自不同线程的多个消费者需要协调对共享队列的访问,并且消费者本身是多线程的。在这种情况下,单个公共锁定对象可以从队列中检索元素,但是消费者的不同部分中的单个共享对象可能成为应用程序的瓶颈。相反,您只想为每个活动对象/使用者锁定一次。您需要lock部分接受一个变量,该变量指示哪个对象需要保护,而不会锁定整个数据集。