【发布时间】:2017-07-29 20:53:51
【问题描述】:
假设我有以下代码:
// global variable
int i = 0;
...
EnterCriticalSection(&CriticalSection);
i = 45;
i = 24;
i = 32;
LeaveCriticalSection(&CriticalSection);
CPU能否缓存变量i,当i被修改时,缓存的副本就是修改的那个,而当LeaveCriticalSection()被调用时,i的缓存值被刷新到内存中(所以例如其他线程可以看到更新的值)?
【问题讨论】:
-
它可以做任何事情,只要程序的可观察行为符合 C 标准为代码指定的行为
-
@HarryJohnston 最新的 C 标准确实涵盖了多线程。 OP 的编译器是否符合标准是另一回事,但标准总是在设计时考虑到现有的实现
-
@HarryJohnston 是的,我确定。编译器知道 CPU 做了什么并相应地生成程序集
-
@Christopher,实际上,
LeaveCriticalSection引入了内存屏障,因此所有缓存的写入将在返回之前刷新到内存。这种行为没有记录在案,但如果要改变它,地球上几乎所有的多线程应用程序都会崩溃。 -
@Olaf,当然编译器会重新排序语句,但是如果它在调用 API 函数时重新排序内存操作,它最好知道该 API 函数实际做了什么,以及它是否重新排序跨 API 函数的内存操作,进入或离开关键部分,好吧,IMO 这只是病态的。 (如果您更仔细地阅读我所说的内容,您会注意到我将 Visual Studio 归类为“较旧的 C 编译器”,与 C11 编译器不同。是 MM 提出了 C11,我只是对此作出回应。 )
标签: c multithreading winapi