使用volatile关键字和锁语句

本文关键字:语句 关键字 volatile 使用 | 更新日期: 2023-09-27 18:14:35

我在应用程序中得到了"对volatile字段的引用不会被视为volatile"的警告。我明白为什么。

作为一个简单的例子,下面的代码将使问题线程安全,即使我将得到警告仍然?

private volatile int myVal = 10;
private int myNonVolatileNumber = 50;
private static readonly object lockObject = new object();
private void ChangeValue(ref int Value)
{
  lock (lockObject)
  {
    Value = 0;
  }
}
private void MyMethod()
{
  ChangeValue(ref myVal); //Warning here
  ChangeValue(ref myNonVolatileNumber); //no warning
}

使用volatile关键字和锁语句

锁强制双方的内存屏障,所以是的,你的例子是线程安全的。

你几乎自己回答了:

ChangeValue(ref myVal); //Warning here
ChangeValue(ref myNonVolatileNumber); //no warning

编译后的ChangeValue()只有一个副本,其中的代码应该实现'volatile'行为。但是编译器(Jitter)在编译时不能预测所有的调用。唯一的选择是将每个 ref参数视为volatile,这将非常低效。

但是看看@Steven的评论,volatile是无用的,应该避免。

可能不需要在您使用的地方使用volatile关键字。

This SO问题回答了所有应该使用volatile关键字的地方:

在c#中什么时候应该使用volatile关键字?

private int val = 10;
private var valLock = new object();
private int nonVolatileNumber = 50;
private var nonVolatileNumberLock = new object();
public int Value
{
    get { lock(valLock) return val; }
    set { lock(valLock) val = value; }
}
public int NonVolatileNumber
{
    get { lock(nonVolatileNumberLock) return nonVolatileNumber; }
    set { lock(nonVolatileNumberLock) nonVolatileNumber = value; }
}

,这里唯一的风险是后续代码访问该属性的私有成员。

在32位整数的情况下,或者甚至64位系统上的64位整数,因为读取将是原子的,你可以像这样使用Interlocked类…

private int val = 10;
public int Value
{
    get { return val; }
    set { Interlocked.Exchange(ref val, value); }
}

对于更复杂的类型,可以使用ReadWriterLockSlim…

private SomeStructure complex;
private var complexLock = new ReadWriterLockSlim();
public SomeStructure Complex
{
    get
    {
        complexLock.EnterReadLock();
        try
        {
            return complex;
        }
        finally
        {
            complexLock.ExitReadlock();
        }
    }
    set
    {
        complexLock.EnterWriteLock();
        try
        {
            return complex;
        }
        finally
        {
            complexLock.ExitWritelock();
        }
    }
}

这比标准锁好,因为它允许多个同时读。