没有同步的C++多线程

标签 c++ multithreading

C++:我有 2 个线程,每个线程通过执行 n++(n 是全局变量)递增“n”假设我没有使用任何线程同步,我的要求是打印 0,1,2,.... 10.

int n = 0 //global variable

线程 1:

n++;
printf("%d", n);

线程 2:

n++;
printf("%d", n);

在没有线程同步的情况下执行程序会不会有问题,还是满足我的要求(1,2,3...10)。

最佳答案

C++ 标准说这个程序有未定义的行为,任何事情都可能发生。 任何,包括重复打印相同的数字、不打印任何内容、程序崩溃或删除硬盘。

1.10 [介绍.多线程]

Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one reads or modifies the same memory location.
...
The execution of a program contains a data race if it contains two potentially concurrent conflicting actions, at least one of which is not atomic, and neither happens before the other, except for the special case for signal handlers described below. Any such data race results in undefined behavior.

你应该使用 std::atomic<int>对于由多个线程同时修改的变量,或与互斥量同步,以避免由于数据竞争导致的未定义行为。

对于您的用例,您需要确保每次更新变量时都打印它的值,即增量和打印必须以原子方式发生。简单地以原子方式更新整数是不够的,您必须确保打印该增量的结果,而不是在稍后的某个时间打印变量的值(当另一个线程可能已经更改它时,如 Rotem 的回答所示)。

可以这样做:

std::atomic<int> n{0}; // global variable

线程 1:

printf("%d", ++n);

线程 2:

printf("%d", ++n);

现在每次线程递增变量时,递增的结果将直接传递给printf。 .

这假设写入 stdout是线程安全的并且按顺序发生,为了避免这种假设,使用互斥锁创建一个临界区来更新变量并打印它,防止其他线程在互斥锁被锁定时增加变量或打印:

int n = 0 //global variable
std::mutex mtx; // global mutex

线程 1:

{
  std::lock_guard<std::mutex> lock(mtx);
  ++n;
  printf("%d", n);
}

线程 2:

{
  std::lock_guard<std::mutex> lock(mtx);
  ++n;
  printf("%d", n);
}

注意仍然不能保证这两个线程会交替递增和打印,第一个线程完全有可能执行十次递增并打印整个输出,而第二个线程没有机会运行。

关于没有同步的C++多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32990177/

相关文章:

c++ - Qt 自定义小部件不显示子小部件

c++ - 视频的持续时间 (OpenCV)

c++ - 多线程计算mean和std并不能提高效率

.net - CLR识别的线程

java - 运行处理程序时出现问题?

java - 我应该同步我的方法吗?

c++ - 在 OO 设计中避免 RTTI

android - 如何通过 JNI 正确地将 YUV_420_888 图像缓冲区从 Java 传递到 OpenCV,考虑步幅/填充

c++ - 编译时检查模板类型 C++

java - 线程开始运行并自行终止