在C#中使用Interlocked获取并设置线程是否安全?

时间:2014-05-28 19:48:33

标签: c# multithreading thread-safety interlocked

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

示例:

public class A()
{
    private static long count;

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

它不是线程安全的。试试这段代码:

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();
}

当运行此代码时,答案不是100_000,而是稍微低一点,证明它不是线程安全的。不知道为什么会发生这种情况