Sam*_*Sam 1 c++ multithreading
C++:我有2个线程,每个线程通过做n ++(n是全局变量)递增'n'假设我没有使用任何线程同步,我的要求是打印0,1,2,.... 10.
int n = 0 //global variable
Run Code Online (Sandbox Code Playgroud)
线程1:
n++;
printf("%d", n);
Run Code Online (Sandbox Code Playgroud)
线程2:
n++;
printf("%d", n);
Run Code Online (Sandbox Code Playgroud)
在没有线程同步的情况下执行程序会有任何问题,或者它是否满足我的要求(1,2,3 ... 10).
C++标准说这个程序有不确定的行为,任何事情都可能发生.任何东西,包括重复打印相同的数字,不打印任何东西,崩溃程序或擦拭硬盘.
1.10 [intro.multithread]
如果其中一个修改内存位置(1.7)而另一个读取或修改相同的内存位置,则两个表达式评估会发生冲突.
...
程序的执行包含数据竞争,如果它包含两个可能同时发生冲突的动作,其中至少有一个不是原子的,并且除了下面描述的信号处理程序的特殊情况之外,它们都不会发生在另一个之前.任何此类数据争用都会导致未定义的行为.
您应该使用std::atomic<int>由多个线程同时修改的变量,或者与互斥锁同步,以避免由于数据争用导致的未定义行为.
对于您的用例,您需要确保每次更新变量时都要打印其值,即增量和打印必须以原子方式进行.简单地以原子方式更新整数是不够的,你必须确保打印该增量的结果,而不是稍后打印变量的值(当另一个线程可能已经改变它时,如Rotem的答案所示).
这可以这样做:
std::atomic<int> n{0}; // global variable
Run Code Online (Sandbox Code Playgroud)
线程1:
printf("%d", ++n);
Run Code Online (Sandbox Code Playgroud)
线程2:
printf("%d", ++n);
Run Code Online (Sandbox Code Playgroud)
现在每次线程递增变量时,该增量的结果将直接传递给printf.
这假设写入stdout是线程安全的并按顺序发生,以避免该假设使用互斥锁创建更新变量并打印它的关键部分,防止其他线程在互斥锁被锁定时递增变量或打印:
int n = 0 //global variable
std::mutex mtx; // global mutex
Run Code Online (Sandbox Code Playgroud)
线程1:
{
std::lock_guard<std::mutex> lock(mtx);
++n;
printf("%d", n);
}
Run Code Online (Sandbox Code Playgroud)
线程2:
{
std::lock_guard<std::mutex> lock(mtx);
++n;
printf("%d", n);
}
Run Code Online (Sandbox Code Playgroud)
NB仍然无法保证两个线程将交替递增和打印,完全有可能第一个线程将执行十个增量并打印整个输出,而第二个线程没有机会运行.
| 归档时间: |
|
| 查看次数: |
267 次 |
| 最近记录: |