mingw 4.6.1原子失败?

时间:2011-12-14 01:00:36

标签: mingw c++11 atomic boost-thread

所以我发现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    

1 个答案:

答案 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还没有支持,或者配置中缺少某些内容。