让另一个线程进入睡眠状态

时间:2019-06-02 17:34:48

标签: c++ multithreading

我有一个对象std :: vector的向量,而fo对象有一个方法start(),其中我创建了特定于该对象的线程,现在依赖于该对象的变量,我想将其置于睡眠状态。 因此,例如,如果我的对象是f1且变量是bool sleep = false;,则当sleep变量为true时,我希望它进入睡眠状态。

我已经尝试过这种方法,但是它似乎不起作用。我认为如果

class fo {

public :
    thread* t ;
    bool bedient = false , spazieren = false;
    void start(){
    t =  new thread([this]() {
        while (!this->bedient){
            if (this->spazieren == true){

                std::this_thread::sleep_for(std::chrono::seconds(10));
                this->spazieren = false ;
            }
        }
        this->join();
    });
    }
    void join(){
    t->join(); delete t;
    }
};

2 个答案:

答案 0 :(得分:1)

您在代码上“产生了”很多问题:

1) 在一个线程中设置任何种类的变量可能在任何其他线程中都不可见。如果要让其他线程看到您在第一个线程中所做的更改,则必须同步内存。这可以通过对数据的每次更改使用std::atomic进行锁定和解锁,或者使用class fo { public : std::thread* t=nullptr ; // prevent corrupt delete if no start() called! std::atomic<bool> bedient = false ; std::atomic<bool> spazieren = false; void start() { t = new std::thread([this]() { while (!this->bedient) { if (this->spazieren == true) { std::cout << "We are going to sleep" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(3)); this->spazieren = false ; } } std::cout << "End loop" << std::endl; }); } ~fo() { delete t; } void join() { std::cout << "wait for thread ends" << std::endl; t->join(); } }; int main() { fo f1; f1.start(); sleep(1); f1.spazieren = true; sleep(1); f1.bedient = true; f1.join(); } 变量来完成,这些变量本身可以进行同步或其他许多方法。请阅读有关多线程编程的书!

2) 您尝试加入自己的线程。那根本不是正确的用法。任何线程都可以在其他执行端联接,但不能在其自身联接。没道理!

3) 如果您没有手动设置“ sleep”变量,则您的线程正在运行一个循环,并且什么也不做。加热内核和行星的好方法;)

using namespace std

顺便说一句:

  1. 请不要使用<form asp-controller="PanelController" asp-action="AddCatAndSubAndBrand" method="post">
  2. 您的设计似乎有问题。从外部线程设置var以控制线程的执行通常是一种滥用。您应该重新考虑您的设计!
  3. 手动使用new / delete可能会导致内存泄漏。
  4. 使用start()方法创建某些内容(以后将被删除)是神秘的。您应该在构造函数中创建所有对象。

答案 1 :(得分:0)

我会尝试将您的代码重构为使用std :: future而不是std :: thread,此外,我相信您会在短期内遇到一些问题。

  1. 您不应在正在加入的线程中尝试加入。也就是说,您拥有的代码将永远不会终止。您定义的lambda将尝试调用join,但是lambda将永远不会返回,因为它正在等待join,而lambda这样做时,lambda本身只会返回。换句话说,您是在告诉它自己等待。
    1. 您向外界透露了有关您班级功能的太多信息。我建议将实现细节移到.cc中,而不是将其放入类声明中。除此之外,您还可以立即访问控制变量spazieren和bedient。这是一个问题,因为它使控制流变得复杂,并导致较弱的抽象。
    2. 您的布尔值不是原子的。如果试图从线程外部修改它们,那么它们将被读取并崩溃。在某些环境中,这些崩溃可能是零星的,很难调试。
    3. 如果您绝对需要尽快完成任务,则只有在被询问时睡觉才有用,但是请注意,这将使核心工作量最大化,并且如果将其部署到错误的环境中可能会导致重大问题和速度下降。我不知道该程序的最终目标是什么,但是我建议考虑将以下代码示例中的输出更改为-一定时间的睡眠时间,10 ms应该足以防止对您造成太大的压力cpu。
    4. 关于您的线程是否正在运行的线程状态在您的实现中不清楚。我建议考虑考虑使用一个附加的bool来指示它是否正在运行,以便您可以更正确地确定start()被多次调用时的处理方式。
    5. 此对象破坏后,如果线程仍在运行,它将崩溃。您需要确保在析构函数也完成运行之前加入。

我会考虑以下重构:

#include <memory>
#include <future>
#include <atomic>

class fo 
{
public:
    ~fo()
    {
        this->_bedient = true;
        _workThread.wait();
    }

    void start()
    {
        _workThread = std::async(std::launch::async, [this]() -> bool
            {
                    while(!this->_bedient) 
                    {
                        if(true == this->_spazieren)
                        {

                            std::this_thread::sleep_for(std::chrono::seconds(10));
                            this->_spazieren = false;
                        }
                        else
                        {
                            std::this_thread::yield();
                        }
                    }
                    return true;
            });
    }

    void ShouldSleep(bool shouldSleep)
    {
        this->_spazieren = shouldSleep;
    }

    void ShouldStop(bool shouldStop)
    {
        this->_bedient = !shouldStop;
    }

private:
    std::future<bool> _workThread = {};
    std::atomic<bool> _bedient{ false };
    std::atomic<bool> _spazieren{ false };
};