具有全局变量的 C++ 多线程

Posted

技术标签:

【中文标题】具有全局变量的 C++ 多线程【英文标题】:C++ Multithread with global variables 【发布时间】:2011-06-23 07:32:41 【问题描述】:

有人知道原始全局变量是否是线程安全的吗?

// global variable
int count = 0;

void thread1()

   count++;


void thread2()

   count--;
   if (count == 0) print("Stuff thing");

如果count没有任何锁定保护,我可以这样做吗?

谢谢。

【问题讨论】:

【参考方案1】:

这不是线程安全的。你在这里有一个竞争条件。原因是,count++ 不一定是原子的(意味着不是单个处理器操作)。该值首先加载,然后递增,然后写回。在每个步骤之间,其他线程也可以修改该值。

【讨论】:

【参考方案2】:

不,不是。 可能取决于实现、编译时选项甚至月相。

但标准并没有强制要求某些东西是线程安全的,特别是因为在当前标准中没有线程安全。

有关此类问题的更详细分析,另请参阅 here。

如果您使用的环境支持线程,则可以使用互斥锁:例如,检查 POSIX 线程下的 pthread_mutex_* 调用。

如果您正在为 C++0x/C++11 编码,请使用互斥体或该标准中详述的原子操作之一。

【讨论】:

【参考方案3】:

只有在您的 PC 上有 1 个具有 ++ 和 -- 原子操作的 CPU 时,它才是线程安全的。

如果你想让它成为线程安全的,这是 Windows 的方式:

LONG volatile count = 0; void Thread1() ::InterlockedIncrement( &count ); void Thread2() if(::InterlockedDecrement( &count ) == 0 ) printf("Stuf");

【讨论】:

只有当内存读取/修改/写入周期本身是原子的时才会如此。即使是 1-CPU 机器也可以执行多任务并在周期中途切换。 你是对的。我可能不得不提到,只有 1 个 CPU 使用 ++ -- 原子操作。 那么这是更新你的答案的好时机,轻推轻推眨眼:-)【参考方案4】:

要让两个或更多线程同时安全地使用一个对象,您需要两件事:操作的原子性和顺序保证。

有些人会假装在某些平台上你在这里尝试的东西是安全的,因为例如int 代表这些平台的任何类型的操作都是原子的(甚至是递增或其他)。这样做的问题是您不一定有订购保证。因此,虽然想知道这个特定的变量将被同时访问,但编译器却不会。 (编译器假设这个变量一次只能被一个线程使用是正确的:你不希望每个变量都被视为潜在共享的。性能后果将是可怕的。)

所以不要以这种方式使用原始类型。您无法从语言中得到任何保证,即使某些平台有自己的保证(例如原子性),您也无法告诉编译器该变量与 C++ 共享。对原子类型、C++0x 原子类型或库解决方案(例如互斥锁)使用编译器扩展。并且不要让名称误导您:要真正有用,原子类型必须提供排序保证以及名称附带的原子性。

【讨论】:

【参考方案5】:

它是一个全局变量,因此多个线程可以竞相更改它。它不是线程安全的。

使用互斥锁。

【讨论】:

在这个特定场景(增量)中,有更快的选项(特定于操作系统),例如 InterlockedIncrement @gigantt.com:Q 没有提到任何平台,所以我认为预期的解决方案应该是独立于平台的。 当然。只是想我会提到它。还值得一提的是 GCC atomic builtins:gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/… @gigantt.com:当然,值得一提,也许你可以把它放在答案中,因为信息确实增加了价值。【参考方案6】:

一般来说,不,你不能逃避。在您的简单示例中,它可能碰巧有效,但并不可靠。

【讨论】:

小心,Pete,内存写入很可能会更新一半的值,然后在更新后半部分之前被切换出去(例如 8051 CPU 的字节操作)。因此,您最终可能会出现从 255 到 256 的 16 位值的转换,其中 0 或 511 取决于哪一半首先更新。换句话说,只有你知道底层的东西是如何运作的,它才是安全的。可移植代码从不安全。

以上是关于具有全局变量的 C++ 多线程的主要内容,如果未能解决你的问题,请参考以下文章

使用具有共享全局变量的线程

java 局部静态变量在多线程环境下是不是有线程安全问题??

Delphi 类变量是不是具有全局或线程本地存储?

python多线程全局变量和锁

JMeter:全局变量___setProperty跨线程传参

多线程访问独立空间全局变量