从usleep唤醒std :: thread

Mat*_*nti 8 c++ multithreading

请考虑以下示例:

#include <iostream>
#include <fstream>
#include <unistd.h>

#include <signal.h>
#include <thread>

void sleepy() {
    usleep(1.0E15);
}

int main() {
    std :: thread sleepy_thread(sleepy);

    // Wake it up somehow...?

    sleepy_thread.join();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们有一个永远睡不着的线程.我想加入它,而不必永远等待它自发地从睡眠中醒来.有没有办法从外部告诉它"嘿,醒来!",以便我可以在合理的时间内加入它?

我绝对不是线程专家,所以如果可能的话,不要假设任何东西.

sba*_*bbi 9

不,不能使用标准库中的线程。

一种可能的解决方法是condition_variable::sleep_for与 amutex和布尔条件一起使用。

#include <mutex>
#include <thread>
#include <condition_variable>

std::mutex mymutex;
std::condition_variable mycond;
bool flag = false;

void sleepy() {
     std::unique_lock<std::mutex> lock(mymutex);
     mycond.wait_for( lock,
                      std::chrono::seconds(1000),
                      []() { return flag; } );
}

int main()
{
    std :: thread sleepy_thread(sleepy);

    {
       std::lock_guard<std::mutex> lock(mymutex);
       flag = true;
       mycond.notify_one();
    }

    sleepy_thread.join();
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用Boost.Thread库,它实现了中断点概念:

#include <boost/thread/thread.hpp>

void sleepy()
{
    // this_thread::sleep_for is an interruption point.
    boost::this_thread::sleep_for( boost::chrono::seconds(1000) );
}

int main()
{
    boost::thread t( sleepy );

    t.interrupt();
    t.join();

}
Run Code Online (Sandbox Code Playgroud)


jag*_*ire 6

其他答案是说您可以使用定时静音来完成此操作。我整理了一个小类,使用定时互斥锁来阻止“睡眠”线程,如果希望尽早“唤醒”它们,则释放互斥锁。标准库提供了一个timed_mutex称为的函数,try_lock_for该函数将尝试锁定互斥锁一段时间,然后再继续操作(并返回失败指示)

可以将其封装在一个类中,例如以下实现,该类仅允许单个调用唤醒等待的线程。还可以通过包含一个waitUntil等待直到一个时间序列与timed_mutex另一个定时等待函数相对应的函数来进行改进,try_lock_until但是我将其留给有兴趣的人练习,因为它看起来很简单。


#include <iostream>
#include <mutex>
#include <thread>
#include <chrono>
#include <atomic>

// one use wakable sleeping class
class InterruptableSleeper{
    std::timed_mutex
        mut_;
    std::atomic_bool
        locked_; // track whether the mutex is locked
    void lock(){ // lock mutex
        mut_.lock();
        locked_ = true;
    }
    void unlock(){ // unlock mutex
        locked_ = false;
        mut_.unlock();
    }
public:
    // lock on creation
    InterruptableSleeper() {
        lock();
    }
    // unlock on destruction, if wake was never called
    ~InterruptableSleeper(){
        if(locked_){
            unlock();
        }
    }
    // called by any thread except the creator
    // waits until wake is called or the specified time passes
    template< class Rep, class Period >
    void sleepFor(const std::chrono::duration<Rep,Period>& timeout_duration){
        if(mut_.try_lock_for(timeout_duration)){
            // if successfully locked, 
            // remove the lock
            mut_.unlock();
        }
    }
    // unblock any waiting threads, handling a situation
    // where wake has already been called.
    // should only be called by the creating thread
    void wake(){
        if(locked_){
            unlock();
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

如下代码:

void printTimeWaited(
  InterruptableSleeper& sleeper, 
  const std::chrono::milliseconds& duration){
    auto start = std::chrono::steady_clock::now();
    std::cout << "Started sleep...";
    sleeper.sleepFor(duration);
    auto end = std::chrono::steady_clock::now();
    std::cout 
        << "Ended sleep after "
        << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
        << "ms.\n";
}

void compareTimes(unsigned int sleep, unsigned int waker){
    std::cout << "Begin test: sleep for " << sleep << "ms, wakeup at " << waker << "ms\n";
    InterruptableSleeper
        sleeper;
    std::thread
        sleepy(&printTimeWaited, std::ref(sleeper), std::chrono::milliseconds{sleep});
    std::this_thread::sleep_for(std::chrono::milliseconds{waker});
    sleeper.wake();
    sleepy.join();
    std::cout << "End test\n";
}

int main(){

    compareTimes(1000, 50);
    compareTimes(50, 1000);

}
Run Code Online (Sandbox Code Playgroud)

版画

Begin test: sleep for 1000ms, wakeup at 50ms
Started sleep...Ended sleep after 50ms.
End test
Begin test: sleep for 50ms, wakeup at 1000ms
Started sleep...Ended sleep after 50ms.
End test
Run Code Online (Sandbox Code Playgroud) 范例和在Coliru上的使用


Rit*_*esh 0

一种可能的方法:(有很多方法可以完成......而且在线程中使用睡眠也不是一个好主意)

///Define a mutex
void sleepy()
{
    //try to take mutex lock which this thread will get if main thread leaves that
    //usleep(1.0E15);
}


int main()
{
    //Init the Mutex
    //take mutex lock
    std :: thread sleepy_thread(sleepy);

    //Do your work
    //unlock the mutex...This will enable the sleepy thread to run
    sleepy_thread.join();
}
Run Code Online (Sandbox Code Playgroud)

  • _“在线程中使用睡眠并不是一个好主意”_那为什么呢? (7认同)
  • 您应该充实答案的“std::mutex”部分。 (2认同)