多线程有时会给出不同的输出
multithreading gives different output sometimes
我目前正在尝试更好地理解多线程,并且正在尝试使用 std::thread。
我有这段代码:
volatile int m = 0;
void ThdFun(int i)
{
for (int j = 0; j < i; ++j) {
m++;
//std::cout << "hello1 " << m << " " <<std::endl;
}
//std::cout << "Hello World from thread " << i <<" " << std::endl;
}
int main(){
int var = 100000; //changes when i want to experiment with diff values
std::thread t1(ThdFun, var);
std::thread t2(ThdFun, var);
t1.join();
t2.join();
std::cout << "final result of m: " << m << std::endl;
if ((var * 2) == m) {
std::cout << "CORRECT" << std::endl;
}
else
std::cout << "INCORRECT" << std::endl;
return 0;
}
我注意到,如果我的 var = 2
或 var =50
,我得到正确的输出(分别是 4 和 100)
但是当我将 var
设为 100000 之类的大数字时,我会得到 100000-200000 范围内的任何值,而我预计会得到 200000。我想知道为什么会这样,因为我的理解 'join()' 函数不应该让它按顺序运行吗?另外,为什么 'smaller' 数字的输出很好,但对于更大的数字却变得不可预测?是 1 个线程完成并因此退出程序还是什么?
有人能解释一下是什么导致了大数字的这种不同输出,以及为什么 join() 不能很好地处理大数字吗?
谢谢!
您的问题是 m++;
行。它真正的作用是这样的:
- 从内存中读取
m
到寄存器中
- 增加寄存器值
- 将寄存器值写回
m
您的代码的问题是对 m
的访问在线程之间不同步,因此一个线程可能会读取 m
(第 1 步)并且在它到达之前写回增量值(第 3 步),另一个线程已读取 m
.
的旧值
在那种情况下,两个线程都读取并递增该值,就像另一个线程递增它之前的值一样,因此您失去了一个递增。
解决这个问题的方法是添加同步。
还好这个很简单,把m
的定义改成std::atomic_int
就可以了。当声明变量atomic时,语言保证m++操作不能被另一个线程中断。
atomic 的替代方法是使用互斥锁,但如果只有一次访问,则最好使用 atomic。
我目前正在尝试更好地理解多线程,并且正在尝试使用 std::thread。
我有这段代码:
volatile int m = 0;
void ThdFun(int i)
{
for (int j = 0; j < i; ++j) {
m++;
//std::cout << "hello1 " << m << " " <<std::endl;
}
//std::cout << "Hello World from thread " << i <<" " << std::endl;
}
int main(){
int var = 100000; //changes when i want to experiment with diff values
std::thread t1(ThdFun, var);
std::thread t2(ThdFun, var);
t1.join();
t2.join();
std::cout << "final result of m: " << m << std::endl;
if ((var * 2) == m) {
std::cout << "CORRECT" << std::endl;
}
else
std::cout << "INCORRECT" << std::endl;
return 0;
}
我注意到,如果我的 var = 2
或 var =50
,我得到正确的输出(分别是 4 和 100)
但是当我将 var
设为 100000 之类的大数字时,我会得到 100000-200000 范围内的任何值,而我预计会得到 200000。我想知道为什么会这样,因为我的理解 'join()' 函数不应该让它按顺序运行吗?另外,为什么 'smaller' 数字的输出很好,但对于更大的数字却变得不可预测?是 1 个线程完成并因此退出程序还是什么?
有人能解释一下是什么导致了大数字的这种不同输出,以及为什么 join() 不能很好地处理大数字吗?
谢谢!
您的问题是 m++;
行。它真正的作用是这样的:
- 从内存中读取
m
到寄存器中 - 增加寄存器值
- 将寄存器值写回
m
您的代码的问题是对 m
的访问在线程之间不同步,因此一个线程可能会读取 m
(第 1 步)并且在它到达之前写回增量值(第 3 步),另一个线程已读取 m
.
在那种情况下,两个线程都读取并递增该值,就像另一个线程递增它之前的值一样,因此您失去了一个递增。
解决这个问题的方法是添加同步。
还好这个很简单,把m
的定义改成std::atomic_int
就可以了。当声明变量atomic时,语言保证m++操作不能被另一个线程中断。
atomic 的替代方法是使用互斥锁,但如果只有一次访问,则最好使用 atomic。