使用boost线程:发出信号并等待终止

Dan*_*ann 2 c++ multithreading boost

我目前正在编写ac/c ++ dll以供以后在Delphi中使用,我对Delphi中的线程比c/c ++更熟悉,尤其是boost.所以我想知道如何实现以下场景?

class CMyClass
{
    private:
        boost::thread* doStuffThread;
    protected:
        void doStuffExecute(void)
        {
            while(!isTerminationSignal()) // loop until termination signal
            {
                // do stuff
            }

            setTerminated(); // thread is finished
        };
    public:
        CMyClass(void)
        {
            // create thread
            this->doStuffThread = new boost::thread(boost::bind(&CMyClass::doStuffExecute, this));
        };

        ~CMyClass(void)
        {
            // finish the thread
            signalThreadTermination();
            waitForThreadFinish();

            delete this->doStuffThread;

            // do other cleanup
        };
}
Run Code Online (Sandbox Code Playgroud)

我有关于提升线程,信号和互斥量的红色无数文章,但我不明白,可能是因为它是星期五;)或者我认为这样做是不可行的?

关心丹尼尔

Jon*_*ely 8

只需使用原子布尔值来告诉线程停止:

class CMyClass
{
private:
    boost::thread doStuffThread;
    boost::atomic<bool> stop;
protected:
    void doStuffExecute()
    {
        while(!stop) // loop until termination signal
        {
            // do stuff
        }

        // thread is finished
    };
public:
    CMyClass() : stop(false)
    {
        // create thread
        doStuffThread = boost::thread(&CMyClass::doStuffExecute, this);
    };

    ~CMyClass()
    {
        // finish the thread
        stop = true;
        doStuffThread.join();

        // do other cleanup
    };
}
Run Code Online (Sandbox Code Playgroud)

要等待线程完成,只需加入它,它将阻塞直到它完成并可以加入.无论如何你需要加入线程才能销毁它,否则它将终止你的程序.

无需使用指针并创建线程new,只需boost::thread直接使用对象即可.在堆上创建所有东西都是浪费,不安全和糟糕的风格.

无需使用boost::bind将参数传递给thread构造函数.许多年来boost::thread一直支持直接将多个参数传递给它的构造函数,并且它在内部进行绑定.

在创建新线程之前stop已经初始化是很重要的false,否则如果新线程很快生成它可以检查stop它在初始化之前的值,并且可能碰巧true从未初始化的内存读取值,然后它会永远不要进入循环.

在风格主题上,foo(void)许多C++程序员认为写作是一种恶心的憎恶.如果你想说你的函数没有参数那么就写foo().

  • @BrandonKohn多线程是单线程,因为相对论是经典力学.**你对同时性和事件顺序的直觉不会延续**.此外,您引用的有关竞争条件的问答并非特定于C++.对于C++,标准有一个非常精确的声明,这是唯一相关的引用. (10认同)
  • **未定义行为**的哪一部分与您无关?如果没有原子,编译器就可以将循环转换为:`if(!stop)while(true){/*do work*/}`因为它知道读取的非原子非易失性变量不能改变,除非在具有未定义行为的程序中,因此它可以假设它永远不会更改 (8认同)
  • 请参阅我以前的评论,或阅读[良性数据竞赛:可能出现什么问题?](https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-可以-可能-GO-错了).仅仅因为你不理解这个问题并不意味着它不是真的. (7认同)
  • 另外,[如何使用"良性"数据竞赛错误编译程序]中的第2.3节(https://www.usenix.org/legacy/event/hotpar11/tech/final_files/Boehm.pdf)就是*这种情况.这两个链接是由一些世界顶尖的数据竞赛和多线程专家编写的,但是,嘿,也许他们只是偏执狂而且你是对的. (7认同)
  • `volatile`对于C++中的线程间通信既不必要也不充分.http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484 (5认同)
  • 我没有说它会阻止它_happening_我说它不一定会及时地被其他线程看到,如果有的话."原子同步的成本"正是使代码正确所需的.如果您决定不需要使用原子来避免数据争用,请不要为我依赖的任何内容编写任何多线程代码. (4认同)
  • 标准非常明确:"两个表达式评估_conflict_如果其中一个修改了内存位置(1.7),另一个访问或修改了相同的内存位置....程序的执行包含_data race_如果它包含两个潜在的并发冲突动作,其中至少有一个不是原子的,也不会发生在另一个之前......任何此类数据竞争都会导致未定义的行为." 此外,如果没有`std :: atomic`提供的内存障碍,则无法保证其他线程将会观察到`stop = true`更新. (3认同)
  • @Puppy Quantum phyiscs更像是UB或heisenbugs.看看它,它已经消失了.多线程实际上就像是相对论,因为它与你对事件相对排序的直觉相混淆. (3认同)
  • @BrandonKohn这个链接早于第一次在c ++*中定义多线程的c ++ 11标准*. (3认同)
  • @BrandonKohn,一个线程将一个值写入布尔值,另一个线程读取它.这似乎是多个线程访问它. (2认同)
  • 它是竞争条件的定义!C++标准说任何数据竞争都是未定义的行为. (2认同)
  • @BrandonKohn"我不认为有不确定的行为." [它是,**在C++**的背景下](http://stackoverflow.com/questions/25082563/25082904#comment39026862_25082904).或者你可能不知道[在程序中使用UB的含义.](http://stackoverflow.com/questions/24296571)"我想知道如果bool被标记为不稳定会发生什么." - [这不够*](http://stackoverflow.com/questions/2484980/why-is-volatile-not-considered-useful-in-multithreaded-c-or-c-programming).此外,在展示实际论点方面没有任何情感. (2认同)
  • @BrandonKohn:嗯,你"思考"的是什么,实际上真实的是两件截然不同的事情.您预先定义的"正确的东西"概念同样存在缺陷,它表明您没有费心阅读呈现给您的材料.您是否知道Jonathan Wakely是世界顶级C++专家之一,开发GCC的C++标准库实现,并且是ISO C++委员会的成员?是啊.那是你在争论的人.但是,嘿,你知道的最好...... (2认同)