在c# get和set中使用互锁是线程安全的

本文关键字:线程 安全 get set | 更新日期: 2023-09-27 18:05:50

是否可以通过在属性访问器中使用Interlocked来获得线程安全属性?

的例子:

public class A()
{
    private static long count;
    public static long Count
    {
        get
        {
            return Interlocked.Read(ref count);
        }
        set
        {
           Interlocked.Exchange(ref count, value); 
        }
    }
}

在c# get和set中使用互锁是线程安全的

当上面的例子运行时,getset访问器的执行行为是线性的。在不使用Interlocked的情况下,getset访问器的执行行为介于弱一致性和顺序一致性之间(即只保证表现弱一致性)。

作为64位进程运行时,可以通过标记字段volatile并使用简单的返回语句和赋值操作符来完成相同的操作。但是,当作为32位进程运行时,不能保证对volatile 64位字段的操作是原子性的,因此需要使用Interlocked来确保原子性。

这不是线程安全的。试试下面的代码:

long i
{
    get { return Interlocked.Read(ref _i); }
    set { Interlocked.Exchange(ref _i, value); }
}

long _i;
void Main()
{
    Parallel.ForEach(Enumerable.Range(0, 1000_000), 
        //new ParallelOptions { MaxDegreeOfParallelism = 1},
        x=>
    {
        i++;
    });
    i.Dump();
}

当您运行这段代码时,答案不是1000_000,而是稍微低一点,证明它不是线程安全的。不知道为什么会这样