Tar*_*Tar 3 c# multithreading memory-barriers
来自O'Reilly的C#in a Nutshell:
class Foo
{
int _answer;
bool _complete;
void A()
{
_answer = 123;
Thread.MemoryBarrier(); // Barrier 1
_complete = true;
Thread.MemoryBarrier(); // Barrier 2
}
void B()
{
Thread.MemoryBarrier(); // Barrier 3
if (_complete)
{
Thread.MemoryBarrier(); // Barrier 4
Console.WriteLine (_answer);
}
}
}
Run Code Online (Sandbox Code Playgroud)
假设方法A和B在不同的线程上并发运行:
作者说:"障碍1和4阻止这个例子写"0".障碍2和3提供了新鲜度保证:他们确保如果B在A之后运行,则读取_complete将评估为真.
我的问题是:
内存屏障强制对来自内存的读写进行排序约束:在屏障发生之前的内存访问操作 - 在屏障之后的内存访问之前.
壁垒1和4具有互补作用:屏障1确保了写至_answer之前发生的写入_complete,而屏障4确保读取从_complete之前发生从读取_answer.想象屏障4不存在,但屏障1是.虽然保证123写入_answer之前true写入_complete其他一些线程,但运行B()仍然可以重新排序其读取操作,因此它可能在读取_answer之前读取_complete.同样,如果屏障1与屏障4删除保存:当从读_complete中B()总是会发生,从之前的读取_answer,_complete仍然可以写入之前_answer从其他线程运行A().
障碍物2和3提供了新鲜度保证:如果障碍物3在障碍物2之后执行,那么A()当它执行障碍物2时,在其执行障碍物2的点处运行的线程可见的状态变得对于在B()执行障碍物3时运行的线程可见.完成B()后执行的这两个障碍中的任何一个都A()可能看不到所做的更改A().特别是屏障2防止写入的值_complete被处理器运行缓存A()并强制处理器将其写入主存储器.类似地,屏障3防止处理器运行B()依赖于高速缓存来_complete强制从主存储器读取的值.但是请注意,在没有内存屏障2和3的情况下,过时缓存不是唯一可以防止新鲜度保证的事情.对内存总线上的操作进行重新排序是这种机制的另一个例子.
内存屏障只是确保内存访问操作的效果跨屏障排序.其他指令(例如,递增寄存器中的值)仍然可以重新排序.
| 归档时间: |
|
| 查看次数: |
676 次 |
| 最近记录: |