我在只有计数器的类中有属性定义,这必须是线程安全的,这不是因为 get
和 set
不在同一个锁中,如何做到这一点?
private int _DoneCounter;
public int DoneCounter
{
get
{
return _DoneCounter;
}
set
{
lock (sync)
{
_DoneCounter = value;
}
}
}
最佳答案
如果您希望以保证 DoneCounter = DoneCounter + 1
不受竞争条件影响的方式实现属性,则不能在属性的实现中完成。该操作不是原子操作,它实际上是三个不同的步骤:
- 检索
DoneCounter
的值。 - 加1
- 将结果存储在
DoneCounter
中。
您必须防止在任何这些步骤之间发生上下文切换的可能性。锁定在 getter 或 setter 内部不会有帮助,因为该锁的范围完全存在于其中一个步骤(1 或 3)中。如果您想确保所有三个步骤一起发生而不被打断,那么您的同步必须涵盖所有这三个步骤。这意味着它必须发生在包含所有这三个方面的上下文中。这可能最终成为不属于任何包含 DoneCounter
属性的类的代码。
使用您的对象的人有责任注意线程安全。通常,不能以这种方式使具有读/写字段或属性的类成为“线程安全的”。但是,如果您可以更改类的接口(interface),从而不需要 setter,则可以使其更加线程安全。例如,如果您知道 DoneCounter 只会递增和递减,那么您可以像这样重新实现它:
private int _doneCounter;
public int DoneCounter { get { return _doneCounter; } }
public int IncrementDoneCounter() { return Interlocked.Increment(ref _doneCounter); }
public int DecrementDoneCounter() { return Interlocked.Decrement(ref _doneCounter); }
关于c# - 如何轻松使这个计数器属性线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9011908/