我遇到了函数InterlockedExchange,并想知道何时应该使用此函数。在我看来,在x86处理器上设置32位值应该始终是原子的?
在我想使用该函数的情况下,新值不依赖于旧值(它不是增量操作)。
你能举例说明这种方法是强制性的(我不是在寻找InterlockedCompareExchange)
答案 0 :(得分:11)
除了编写新值之外,InterlockedExchange
还会读取并返回先前的值;整个操作都是原子的。这对lock-free algorithms很有用。
(顺便说一句,32位写入不保证是原子的。例如,考虑写入未对齐并跨越缓存边界的情况。)
答案 1 :(得分:10)
InterlockedExchange
是一个写和读取 - 它返回前一个值。
这是必要的,以确保另一个线程在您执行之后不会写入不同的值。例如,假设您正在尝试增加变量。您可以读取值,添加1,然后使用InterlockedExchange
设置新值。 InterlockedExchange
返回的值必须与您最初读取的值匹配,否则另一个线程可能会同时增加它,您需要循环并再试一次。
答案 2 :(得分:4)
在多处理器或多核计算机中,每个核心都有自己的缓存 - 因此每个核心都拥有可能与系统内存内容不同的“视图”。
线程同步机制负责核心之间的同步,有关更多信息,请查看http://blogs.msdn.com/oldnewthing/archive/2008/10/03/8969397.aspx或google获取和发布语义
答案 3 :(得分:3)
设置32位值是原子的,但仅限于设置文字。
b = a是2个操作:
mov eax,dword ptr [a]
mov dword ptr [b],eax
理论上,第一次和第二次操作之间可能会有一些中断。
答案 4 :(得分:3)
默认情况下,写一个值绝不是原子的。向变量写入值时,会生成多个机器指令。使用现代抢占式操作系统,操作系统可能会切换到写入的各个操作之间的另一个线程。
这在多处理器计算机上更是一个问题,其中多个线程可以同时执行,并尝试同时写入单个内存位置。
互锁操作通过使用专用指令进行写操作来避免这种情况(x86具有针对这种情况的专用指令),它在一条指令中执行读 - 修改 - 写操作。这些指令还锁定所有处理器的内存总线,以确保没有其他正在执行的线程可以同时写入该值。
答案 5 :(得分:2)
InterlockedExchange确保变量的更改及其原始值的返回不会被其他线程中断。
因此,如果'i'是一个int,这些调用(单独采取)不需要在'i'周围进行InterlockedExchange:
a = i;
i = 9;
i = a;
i = a + 9;
a = i + 9;
if(0 == i)
这些陈述都不依赖于'i'的初始和最终值。但是这些以下的呼叫需要在'i'周围进行InterlockedExchange:
a = i++; //a = InterlockedExchange(&i, i + 1);
没有它,两个运行同一代码的线程可能会获得相同的'i'值分配给'a'或'a'可能会意外跳过两个或更多数字。
if(0 == i++) //if(0 == InterlockedExchange(&i, i + 1))
两个线程都可以执行只发生一次的代码 等
答案 6 :(得分:-1)
考虑到上面的半答案,我也不确定答案,但我认为它的工作方式是这样的,我可能错了,找出我是不是很有趣: