所以我发现gcc已经有了std::atomic
的工作实现所以我想尝试一下,这是我使用boost thread 1.48和std::atomic
的例子:
#include <iostream>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <atomic>
#include <string>
using namespace std;
using namespace boost;
class Server
{
public:
atomic<bool> running;
thread main_server_thread;
void func1()
{
while(running)
{
//do stuff
}
}
void func2()
{
while(running)
{
//do stuff
}
}
void func3()
{
while(running)
{
//do stuff
}
}
void func4()
{
string input;
while(running)
{
//do stuff
input.clear();
getline(cin,input);
if(input=="quit")running=false;
}
}
void main_function()
{
thread thrd1(bind(&Server::func1,this));
thread thrd2(bind(&Server::func2,this));
thread thrd3(bind(&Server::func3,this));
thread thrd4(bind(&Server::func4,this));
while(running)
{
//do stuff
}
thrd1.join();
thrd2.join();
thrd3.join();
thrd4.join();
}
Server()
{
running=true;
main_server_thread = thread(&Server::main_function,this);
}
};
int main()
{
Server* serv = new Server();
serv->main_server_thread.join();
return 0;
}
现在虽然running
仍为true
,但一切正常,但当用户输入quit
并且running
设置为false
时,某些主题会结束,而某些主题会结束吨。无论有没有优化都会发生这种情况。这是否按预期工作?在我对原子的理解中,读取不应该与一次写入冲突,因此线程应该在某个时刻看到running=false
。
编辑: 反汇编func1:
void func1()
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
{
while(running)
6: 90 nop
7: 8b 45 08 mov 0x8(%ebp),%eax
a: 89 04 24 mov %eax,(%esp)
d: e8 00 00 00 00 call 12 <__ZN6Server5func1Ev+0x12>
12: 84 c0 test %al,%al
14: 75 f1 jne 7 <__ZN6Server5func1Ev+0x7>
{
//do stuff
}
}
16: c9 leave
17: c3 ret
答案 0 :(得分:1)
正如反汇编所示,当使用mingw编译时,此程序不会将running
视为原子:它加载了常规mov 0x8(%ebp),%eax
而没有同步。
与linux / x86_64上的gcc-4.6.2的输出进行比较:
_ZN6Server5func1Ev: // Server::func1()
jmp .L78
.L79:
// do stuff
.L78:
mfence
movzbl (%rdi), %eax // load from `running`
mfence
testb %al, %al
jne .L79
ret
mingw还没有支持,或者配置中缺少某些内容。