c - InterlockedExchange 在 vmware 下失败,有解决办法吗?

标签 c winapi vmware esxi

一个非常简单的方法。 两个线程。

volatile __int32 p=0;

一个线程(A)仅使用

while(1){
    ExecuteAVeryCPUIntesiveThing();
    InterlockedExchange(&p, 0);
}

另一个线程(B)使用

while(1){
    if(0==InterlockedCompareExchange(&p,0,0))
        InterlockedExchange(&p, 1);
}

如果有人尝试在处于压力下的系统下记录这一点。 (大量内存交换、io、套接字、cpu 峰值..) A 中的值不会传播到 B。

在 A 中,p 的值为 0。 但从 B 的角度来看,p 一直停留在 1。 在我的世界中,当 A 将值设置为 0 时,B 应该检测到并将该值设置为 0。 在实际硬件上,这就像那样工作,但在 esxi 上运行时则不然。

这似乎在真实硬件和某些虚拟系统下工作正常,但在 vmware 下则不然。

我是不是出现了思维失误或者……?

操作系统访客:win2008服务器

使用适用于 x64 的 Microsoft (R) C/C++ 优化编译器版本 15.00.30729.01 编译的代码

主机:esxi 4.1

更新:

回复评论:是的,它会在 0 和 1 之间反弹, 但正如所写,线程 B 不会反弹,因为 p 的值在 B 的视角中永远不会/或不会改变,它会反弹 10-20 次然后停止。

我只想在非常精确的时刻执行 A 中的代码块( ExecuteAVeryCPUIntesiveThing();)。

生产代码充满了更多线程和事件、互斥锁和锁,但事实仍然是,如果我剥离并仅使用上述代码,如果我在 guest 操作系统上生成大量 cpu、mm、io,我可以重现它.

最佳答案

此代码是等待发生的线程竞争。您可能从 VMWare 获得它,因为您只为虚拟机分配了一个处理器。

该代码缺少的是一个互锁,该互锁可确保线程 B 看到 p 的值发生变化。因此,如果线程 A 获得了一个 cpu 核心并保持运行一段时间,而线程 B 被阻塞,等待一个时间片运行,那么线程 A 可以多次将 p 设置为 0。线程 B 将不会注意到这一点,因为它从未有机会将 p 设置回 1。

您需要重新考虑您的锁设计。这个问题不仅限于VMWare,在普通机器上也可能出错,只是可能性小得多。每个月都会出错一次,或多或少,不可能调试。否则,这是一种经典的生产者/消费者场景,您可以使用线程安全队列来解决该场景。

关于c - InterlockedExchange 在 vmware 下失败,有解决办法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10383022/

相关文章:

c - 编译 C 库时的警告

c - 类似于 memcached 的简单 C/C++ 进程内缓存

c - 为什么(带符号的)强制转换有时只需要表示最小整数(32 位系统)?

windows - 如何挂接到 Windows 网络事件

vmware 解锁器错误 : "file not found - darwin*.*"

virtualbox - 无法导入设备。找不到 SCSI Controller

c - 终止 C 中的递归函数

c - Excel 加载项 : Assignment in for loop causes segmentation fault but line-by-line assignments work. 为什么?

c++ - 无法获得设备中的处理器速度

c++ - vmware中的线程编程, 'process scheduling'没有发生