C#中的volatile数组项?

18

我需要一个包含易失性元素的数组,但是找不到实现的方法。

private volatile T[] _arr;

这意味着_arr引用是易变的,但它并不能保证_arr对象内部的任何项目。

有没有办法将_arr的项目标记为易变?

谢谢。

编辑:

根据binarycoder的答案构建了以下代码。这段代码是否线程安全?

public class VolatileArray<T>
{
    private T[] _arr;

    public VolatileArray(int length)
    {
        _arr = new T[length];
    }

    public VolatileArray(T[] arr)
    {
        _arr = arr;
    }

    public T this[int index]
    {
        get
        {
            T value = _arr[index];
            Thread.MemoryBarrier();
            return value;
        }

        set
        {
            Thread.MemoryBarrier();
            _arr[index] = value;
        }
    }

    public int Length
    {
        get { return _arr.Length; }
    }
}

5
这个问题需要更多的关注/赞许。 - Jacobs Data Solutions
当T为longdouble时,它不是线程安全的,因为这些都是64位值,您必须使用Volatile.Read()Volatile.Write()或类似方法来读取和写入它们,否则读取和写入不能保证是原子性的。 - Evgeniy Berezovsky
4个回答

11

由于可以通过引用传递数组元素,因此可以使用Thread.VolatileReadThread.VolatileWrite

理解volatile关键字是如何通过使用Thread.MemoryBarrier来实现的是很有用的。你可以这样写:

// Read
x = _arr[i];
Thread.MemoryBarrier();

// Write
Thread.MemoryBarrier();
_arr[i] = x;

请注意,volatileMemoryBarrier都是高级技术,容易出错。例如,请参见如何理解读内存屏障和volatile。通常情况下,您最好使用更高级别的构造,如lockMonitorReaderWriterLockSlim等。


1
如果我没记错的话,那么严格来说,“volatile”关键字只涉及适当的读或写屏障,而“Thread.MemoryBarrier()”则具有完整的屏障。因此,即使在考虑到它涉及方法调用之前,上述内容仍然比等效使用“volatile”更重。这仍然是我们能做的最好的办法(正如您所说,“VolatileRead()”和“VolatileWrite()”目前的实现方式)。 - Jon Hanna

6
使用Volatile.Read(ref array[index])Volatile.Write(ref array[index], value)
自.NET 4.5以来,类Volatile可用。它允许从/向字段、数组元素、ref参数、指针读取/写入。

他关注的是数组引用的不稳定性,而不是其中的元素。 - Evgeniy Berezovsky
3
他明确表示他需要对数组项进行易失性访问。 - OmariO

3
我创建了一个小的结构体,帮助保持代码整洁和面向对象。
struct VolatileBoolean {
    public volatile Boolean Value;
}

VolatileBoolean[] arrayOfVolatileBooleans;
public void SomeMethod() {
    if (arrayOfVolatileBooleans[4].Value)
        DoSomething();
}

2

我认为你不可能做到

你不能这样做,volatile被定义为一个字段修饰符(ECMA 334)。

而且我认为它也无法实现你想要的效果。
考虑一下:

 private T[] _arr;

 volatile T v;
 ....  v = _arr[x];
 ....  _arr[x] = v;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接