【发布时间】:2012-09-25 22:08:00
【问题描述】:
我有一个使用静态成员变量作为标志的类。该程序是多线程的,并且对静态变量值的更改不会在线程之间一致地进行通信。
代码如下:
MyClass.h 文件:
class MyClass
{
private:
void runLoop();
static bool shutdownRequested;
};
MyClass.cpp 文件:
bool MyClass::shutdownRequested = false; // static variable definition
void MyClass::runLoop()
{
// much code omitted
if (isShutdownNecessary() && !shutdownRequested)
{
shutdownRequested = true; // Race condition, but that's OK
MyLog::Error("Service shutdown requested");
// more code omitted
}
}
我预计上面显示的日志行可能只会出现一次,但由于竞争条件,理论上每个线程可能会出现一次。 (在我的情况下,竞争条件是可以接受的。)但是,我看到日志行在每个线程中出现了几十次。我可以说出来,因为 MyLog 类还记录每个日志行的线程 ID、进程 ID 等。
到目前为止,我仅在 Windows 版本构建中观察到此问题。我还没有在 Windows 调试版本或 Linux 版本中观察到它。
由于在多核处理器的不同内核上运行不同的线程,我可以理解每个线程查看一次日志行。我很惊讶地看到相同的线程一遍又一遍地执行日志行。
任何人都可以阐明可能导致这种情况发生的具体机制,以及我可以做什么(例如同步)来强制更新静态变量的值以被识别?
【问题讨论】:
-
使用
std::atomic<bool>而不是bool- 问题已解决。 (根本问题是你需要一个内存屏障。) -
我应该提到:我不能使用 Boost 或 C++ 的最新添加。我必须使用 Visual Studio 2008。
-
我看不出线程无法看到它自己对变量的更改。所以 AFAICS 你有一些其他问题。很可能在您未显示的代码中。
-
@echawkes :那么您最简单的选择(如果您想避免锁定)是将变量从
bool更改为LONG,并且只能使用InterlockedXXX之一访问它功能。 -
只是一个关于你的问题的问题。如果不同的线程在程序的不同内核上运行,这是否意味着每个线程都会有不同的堆?如果每个程序确实有不同的堆,静态变量将存储在哪里?幕后的静态变量有什么事情吗?
标签: c++ multithreading static-members