我想等待在同时模拟器中执行的2个线程中的一个线程,直到条件发生,可能是在模拟器中运行程序1000个或更多周期后发生的条件,在条件发生后等待的线程再次执行,我该怎么做?
4 回答
你需要条件变量。
如果您的编译器支持std::conditional
C++11 引入的,那么您可以查看详细信息:
如果您的编译器不支持它,并且您使用的是 win32 线程,请查看以下内容:
这是一个完整的例子。
如果您使用 POSIX 线程,请查看以下内容:
你可以在这里看到我conditional_variable
使用 win32 原语的实现:
向下滚动,先看看它的实现,再看看并发队列实现中的用法。
条件变量的典型用法是:
//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()
如果你没有 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()
使用 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”在信号量上发出信号。主线程将在等待节点/点接收信号,然后继续。
尝试这样的事情:
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();