只是在业余时间玩并发,并想尝试在不使用读取器端的锁的情况下防止撕裂读取,因此并发读取器不会相互干扰。
这个想法是通过锁序列化写入,但在读取端仅使用内存屏障。这是一个可重用的抽象,它封装了我提出的方法:
public struct Sync<T>
where T : struct
{
object write;
T value;
int version; // incremented with each write
public static Sync<T> Create()
{
return new Sync<T> { write = new object() };
}
public T Read()
{
// if version after read == version before read, no concurrent write
T x;
int old;
do
{
// loop until version number is even = no write in progress
do
{
old = version;
if (0 == (old & 0x01)) break;
Thread.MemoryBarrier();
} while (true);
x = value;
// barrier ensures read of 'version' avoids cached value
Thread.MemoryBarrier();
} while (version != old);
return x;
}
public void Write(T value)
{
// locks are full barriers
lock (write)
{
++version; // ++version odd: write in progress
this.value = value;
// ensure writes complete before last increment
Thread.MemoryBarrier();
++version; // ++version even: write complete
}
}
}
不要担心版本变量溢出,我用另一种方式避免。那么上面我对 Thread.MemoryBarrier 的理解和应用正确吗?是否有任何障碍是不必要的?