Ole*_*nyk 17 .net c# multithreading
众所周知,引用在32位处理器中占用4字节,在64位处理器中占用8字节.因此,处理器保证以机器的自然字大小为增量单次读取和写入存储器将以原子方式执行.另一方面,Interlocked类有两种方法:
public static int Exchange(
ref int location1,
int value
)
Run Code Online (Sandbox Code Playgroud)
和
public static T Exchange<T>(
ref T location1,
T value
)
where T : class
Run Code Online (Sandbox Code Playgroud)
那么,问题是为什么Int32和参考类型需要Interlocked.Exchange?仅使用简单的赋值就不能安全地完成,因为它是原子的吗?
Dmi*_*try 14
它不仅仅是关于原子性的.它还涉及内存可见性.变量可以存储在主存储器或CPU缓存中.如果变量仅存储在CPU缓存中,则在不同CPU上运行的线程将无法看到该变量.考虑以下示例:
public class Test {
private Int32 i = 5;
public void ChangeUsingAssignment() {
i = 10;
}
public void ChangeUsingInterlocked() {
Interlocked.Exchange(ref i, 10);
}
public Int32 Read() {
return Interlocked.CompareExchange(ref i, 0, 0);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你在一个线程上调用'ChangeUsingAssignment'而在另一个线程上调用'read',则返回值可能是5,而不是10.但是如果你调用ChangeUsingInterlocked,'Read'将按预期返回10.
---------- ------------ -------------------
| CPU 1 | --> | CACHE 1 | --> | |
---------- ------------ | |
| RAM |
---------- ------------ | |
| CPU 2 | --> | CACHE 2 | --> | |
---------- ------------ -------------------
Run Code Online (Sandbox Code Playgroud)
在上图中,"ChangeUsingAssignement"方法可能导致值10在CACHE 2中"卡住"并且不会使其进入RAM.当CPU 1稍后尝试读取它时,它将从RAM中获取值仍然是5.使用Interlocked而不是普通写入将确保值10一直到RAM.
交换内存值和CPU寄存器的内容通常不是原子的.你们都需要读写内存位置.此外,这些Interlocked
方法保证即使在多核计算机上操作也是原子的,其中每个核心都有自己的高速缓存,并且可能有自己的主存储器视图.
归档时间: |
|
查看次数: |
9839 次 |
最近记录: |