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)
在这里,我们有一个永远睡不着的线程.我想加入它,而不必永远等待它自发地从睡眠中醒来.有没有办法从外部告诉它"嘿,醒来!",以便我可以在合理的时间内加入它?
我绝对不是线程专家,所以如果可能的话,不要假设任何东西.
不,不能使用标准库中的线程。
一种可能的解决方法是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)
其他答案是说您可以使用定时静音来完成此操作。我整理了一个小类,使用定时互斥锁来阻止“睡眠”线程,如果希望尽早“唤醒”它们,则释放互斥锁。标准库提供了一个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上的使用
一种可能的方法:(有很多方法可以完成......而且在线程中使用睡眠也不是一个好主意)
///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)