【问题标题】:waiting thread until a condition has been occurred等待线程直到条件发生
【发布时间】:2012-06-14 01:07:16
【问题描述】:
我想等待在同时模拟器中执行的 2 个线程中的一个线程直到条件发生,可能是在模拟器中运行程序 1000 或更多周期后发生的条件,在条件发生后等待的线程又执行了,怎么办?
【问题讨论】:
标签:
c++
multithreading
simulator
【解决方案1】:
你需要条件变量。
如果你的编译器支持C++11引入的std::conditional,那么你可以看看这个详细说明:
如果您的编译器不支持它,并且您使用的是 win32 线程,那么请查看:
而here 就是一个完整的例子。
如果您使用 POSIX 线程,请查看:
你可以在这里看到我使用win32原语实现conditional_variable:
向下滚动,先看它的实现,再看并发队列实现中的用法。
条件变量的典型用法是这样的:
//lock the mutex first!
scoped_lock myLock(myMutex);
//wait till a condition is met
myConditionalVariable.wait(myLock, CheckCondition);
//Execute this code only if the condition is met
whereCheckCondition 是一个检查条件的函数(或函子)。它由wait() 函数内部调用,当它虚假地 唤醒并且如果条件尚未满足,则wait() 函数再次休眠。在睡觉之前,wait()原子地释放了互斥锁。
【解决方案2】:
如果你没有 C++11,但你有一个支持 POSIX 线程的系统,那么你可以使用条件变量。还有其他选择,但考虑到您描述问题的方式,条件变量可能是最直接的。
pthread 条件变量与互斥锁一起使用。条件变量的技巧是等待它会导致获取的互斥锁被释放,直到等待调用返回,此时互斥锁再次被获取。顺序是:
- 获取互斥锁
- 而 PREDICATE 不正确
- 在关键部分工作
- 如果 PREDICATE 为真
- 释放互斥锁
如果多个线程进入上述相同的关键部分,则使用信号步骤。
如果不同的线程可能访问同一个互斥体以修改影响 PREDICATE 的状态,则该线程应检查是否需要向任何人发出信号。
- 获取互斥锁
- 在关键部分工作
- 如果 PREDICATE 为真
- 释放互斥锁
感兴趣的 POSIX 命令是:
pthread_mutex_init()
pthread_mutex_destroy()
pthread_mutex_lock()
pthread_mutex_unlock()
pthread_cond_init()
pthread_cond_destroy()
pthread_cond_wait()
pthread_cond_signal()
【解决方案3】:
使用 Semaphore 发出信号。示例(应用程序清理退出)如下:
在标题中声明
static sem_t semPrepareExit; //declaration
在源(主线程)中;
sem_init(&semPrepareExit, 0, 0); ///semaphore initialized
...
///now wait for the signal on the semaphore, to proceed hereforth
sem_post(&semPrepareExit);
/// cleanup ahead
...
在源代码中,(衍生线程);
...
sem_post(&semPrepareExit);
现在,只要您使用“sem_post”在信号量上发出信号。主线程将在等待节点/点接收信号,然后继续。
【解决方案4】:
试试这样的:
class CmyClass
{
boost::mutex mtxEventWait;
bool WaitForEvent(long milliseconds);
boost::condition cndSignalEvent;
};
bool CmyClass::WaitForEvent(long milliseconds)
{
boost::mutex::scoped_lock mtxWaitLock(mtxEventWait);
boost::posix_time::time_duration wait_duration = boost::posix_time::milliseconds(milliseconds);
boost::system_time const timeout=boost::get_system_time()+wait_duration;
return cndSignalEvent.timed_wait(mtxEventWait,timeout); // wait until signal Event
}
//所以为了等待然后调用WaitForEvent方法
WaitForEvent(1000); // it will timeout after 1 second
// 这就是事件的信号方式:
cndSignalEvent.notify_one();