在第一篇中,我们讲解了linux下锁的概念:
https://blog.csdn.net/zhangkai19890929/article/details/85107046
这一篇我们主要讲解wait()和broadcast的 知识:
首先我们需要介绍的是:
pthread_cond_t代表一个条件变量,pthread_mutex_t代表互斥锁,条件变量要配合互斥锁来完成。
在线程中,条件变量主要有2个比较大的动作:
1.线程等待"条件成立"而挂起
2.另一个线程使"条件成立"
因为同一时间我们只能满足一个 线程等待"条件成立" ,为了防止竞争,我们总是和一个互斥锁配合使用.
接下来我们来讲解实现原理:
1.创建条件变量,并进行初始化
pthread_cond_t event_cond_;
pthread_cond_init(&event_cond_,NULL);
2.等待条件成立的2种方式
永远等待:
error = pthread_cond_wait(&event_cond_,&event_mutex_);
等待一定的时间,如果再等待时间内,条件还没成立,那么就直接返回
error = pthread_cond_timedwait(&event_cond_, &event_mutex_,&ts);
3.激活条件的方式
pthread_cond_signal()激活一个等待条件的线程.
pthread_cond_broadcast()激活所有的等待线程.
接下来我们看看webrtc中的功能实现:
event.h头文件
#include <pthread.h>
class Event {
public:
static const int kForever = -1;
Event(bool manual_reset,bool initially_signaled);
~Event();
void Set();
void Reset();
bool Wait(int milliseconds);
private:
pthread_mutex_t event_mutex_; //互斥锁
pthread_cond_t event_cond_;//条件变量
const bool is_manual_reset_;
bool event_status_;
};
#endif
event.cpp 文件的实现:
class EventWrapperImpl : public EventWrapper {
public:
EventWrapperImpl() : event_(false,false) {}
~EventWrapperImpl() {}
bool Set() override {
event_.Set();
return true;
}
EventTypeWrapper Wait(unsigned long max_time) override {
int to_wait = max_time == 0xffffffff ? Event::kForever : static_cast<int>(max_time);
return event_.Wait(to_wait) ? kEventSignaled : kEventTimeout;
}
private:
Event event_;
};
EventWrapper* EventWrapper::Create() {
return new EventWrapperImpl();
}
Event::Event(bool manual_reset, bool initially_signaled)
: is_manual_reset_(manual_reset),
event_status_(initially_signaled)
{
pthread_mutex_init(&event_mutex_,NULL);
pthread_cond_init(&event_cond_,NULL);
}
Event::~Event() {
pthread_mutex_destroy(&event_mutex_);
pthread_cond_destroy(&event_cond_);
}
void Event::Set() {
pthread_mutex_lock(&event_mutex_);
event_status_ = true;
pthread_cond_broadcast(&event_cond_);
pthread_mutex_unlock(&event_mutex_);
}
void Event::Reset() {
pthread_mutex_lock(&event_mutex_);
event_status_ = false;
pthread_mutex_unlock(&event_mutex_);
}
bool Event::Wait(int milliseconds) {
pthread_mutex_lock(&event_mutex_); //必须先获取锁,避免竞争状态
int error = 0;
if (milliseconds != kForever)
{
struct timespec ts;
struct timeval tv;
gettimeofday(&tv,NULL);
ts.tv_sec = tv.tv_sec + (milliseconds / 1000);
ts.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;
//Handler overflow
if (ts.tv_nsec >= 1000000000)
{
ts.tv_sec++;
ts.tv_nsec -= 1000000000;
}
while (!event_status_ && error == 0) {
error = pthread_cond_timedwait(&event_cond_, &event_mutex_,&ts); //同时会释放出锁event_mutex_,所以在此之前,此线程必须先获取到锁.
}
}
else
{
//永远等待
while (!event_status_ && error == 0) {
error = pthread_cond_wait(&event_cond_,&event_mutex_);
}
}
if (error == 0 && !is_manual_reset_)
event_status_ = false;
return error == 0;
}
OK,在main方法中,我们来实现:
void* thread4(void * client)
{
cout << "thread4 Wait 5 seconds" << endl;
EventWrapper* event = (EventWrapper *) client;
event->Wait(5000);
cout << "thread4 Wait success" << endl;
}
void* thread5(void * client)
{
cout << "thread5 broadcast" << endl;
EventWrapper* event = (EventWrapper *)client;
event->Set();
}
这里我先让线程4暂停5秒,然后让在线程5去通知,可以从结果很明显的看到,线程四在收到通知后,是立刻就退出来了.