多次运行以下代码会产生多次出现相同数字的输出。我不知道为什么会这样。
#include <iostream>
#include <pthread.h>
using namespace std;
const int NUM_THREADS = 5;
void* thread_entry(void *i){
cout<<(long)i<<endl;
}
int main () {
pthread_t threads[NUM_THREADS];
long i;
for(i=0;i<NUM_THREADS;i++){
pthread_create(&threads[i],NULL,&thread_entry,(void *)i);
}
return 0;
}
使用g++ -std=c++11 main.cpp -lpthread
进行编译。
输出:
$ ./a.out
0
1
4
$ ./a.out
014
14
23
$ ./a.out
02
2
3
答案 0 :(得分:2)
该计划的主要问题是:
3不是必需的(如果修复了1和2),因为默认情况下通过std :: cout输出是线程安全的,不是数据争用,而是输出可以交错。
现在,问题的有趣部分
相同的数字不止一次出现。我不确定为什么会这样。
假设您正在使用Linux或类似的东西,当主函数存在时,它会执行exit
,在GNU C运行时,它会执行__run_exit_handlers
,然后调用_IO_cleanup
}。 _IO_cleanup
的工作是写出任何未写入的输出缓冲区。如果发生而其他一个线程正在编写中,例如在write(2)
系统调用中,_IO_cleanup
将查看缓冲区状态并查看它& #39; s仍然&#34;完整&#34; (_IO_file_write
线程中的write(2)
会在从write(2)
返回时更新缓冲区位置指示符。因此,根据清理,缓冲区尚未写入,并且它会在同一缓冲区上启动自己的self.ui.lblImageName.setText(data['image'])
系统调用。
答案 1 :(得分:1)
official docs在这里有正确的答案。真正的问题不是加入线程。我将其余的留在这里作为参考:
您应该以不可预测的顺序看到输出,但它不应该产生重复的值。通常,cout
不是线程安全的:
从C ++ 14:27.2.3 [iostreams.threadsafety]
并发访问流对象(27.8,27.9),流缓冲区对象(27.6)或C库流(27.9.2) 除非另有说明,否则多线程可能会导致数据争用(1.10)(27.4)。 [注:数据竞赛 导致未定义的行为(1.10)。 - 结束说明]
然而,27.4给出了在这种情况下适用的例外:
FILEs,同步访问同步(27.5.3.4)标准iostream对象的格式化和未格式化 - 不得产生put(27.7.2.1)和输出(27.7.3.1)函数或多个线程的标准C流 在数据竞赛中(1.10)。 [注意:用户仍必须同步这些对象和流的并发使用 多个线程,如果他们希望避免交错字符。 - 结束说明]
由于'relabel_configs' => [
{
'source_labels' => '[__meta_consul_node]',
'regex' => '^(.*)$',
'target_label' => 'instance',
'replacement' => '$1',
},
{
'source_labels' => '[__meta_consul_service]',
'regex' => '^(.*)$',
'target_label' => 'job',
'replacement' => '$1',
}
],
已同步,因此应该是线程安全的。
答案 2 :(得分:0)
在多线程中,无法保证线程中的代码将在另一个线程中的代码之前或之后运行而没有任何同步机制。
你有一个主线程和主线程创建的其他线程,你不能指望数字&#39; i&#39; 主线程的循环增加之前不会是
。