从实例化对象读取属性是否是线程安全的?

Jer*_*acs 0 c# singleton thread-safety

我可以安全地IsBusy从多个线程读取实例化单例的布尔属性,而不会导致任何线程安全问题,或者我已经处于危险水域?

Jon*_*eet 5

除非你有任何记忆障碍,否则如果价值可能发生变化,你可能处于危险的水域.

让我们把这个中的单例部分排除在等式之外,因为它不是特别相关.考虑这个简单的例子:

// Not safe!
public class BusyIndicator
{
    public bool IsBusy { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果你有一个线程:

foo.IsBusy = true;
// do some work
foo.IsBusy = false;
Run Code Online (Sandbox Code Playgroud)

和另一个线程,仅在IsBusy设置为true 后启动,具有:

// Do some work
while (foo.IsBusy) { }
Run Code Online (Sandbox Code Playgroud)

...那么第二个线程可能永远旋转......没有内存屏障来确保它"看到"第一个线程的变化.

您可以使用锁定或使用安全地实现此目的Interlocked,例如

// Safe (in terms of memory barriers)
public class BusyIndicator
{
    private int busy = 0;

    public bool IsBusy
    {
        get { return Interlocked.CompareExchange(ref busy, 0, 0) == 1; }
        set { Interlocked.Exchange(ref busy, value ? 1 : 0); }
    }
}
Run Code Online (Sandbox Code Playgroud)