(1) 什么是条件变量实现线程同步?
假如我们的程序中有两个线程,一个是生产者线程,另一个是消费者线程,生产者线程每隔一段时间把数据写入到缓冲区buffer中,而消费者线程则每隔一段时间从buffer中取出数据,为了避免两个线程读写混乱,我们让生产线线程写完后再通知消费者来读数据,那么则可以用条件变量来实现线程的同步。
(2) 条件变量的两个动作
条件不满足: 阻塞线程
条件满足: 通知阻塞的线程开始工作
(3) 条件变量的类型:
pthread_cond_t cond;
(4) 主要函数:
初始化一个条件变量( 第二参数一般为NULL)
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
销毁一个条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
阻塞等待一个条件变量
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
阻塞线程
将已经上锁的mutex解锁
解除阻塞后会对mutex加锁
限时等待一个条件变量
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个。
int pthread_cond_signal(pthread_cond_t *cond);
唤醒全部阻塞在条件变量上的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
(5)注意事项
注意 1:
mutex 互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP)。
在调用 pthread_cond_wait()前必须由本线程加锁 pthread_mutex_lock()。
在更新条件等待队列以前,mutex 保持锁定状态。
在线程挂起进入等待前解锁。
注意 2:
在条件满足从而离开 pthread_cond_wait() 之前,mutex 将被重新加锁,以与进入
pthread_cond_wait()前的加锁动作对应。
也就是说在做 pthread_cond_wait 之前,往往要用 pthread_mutex_lock 进行加锁,而
调 pthread_cond_wait 函 数 会 将 锁 解 开 , 然 后 将 线 程 挂 起 阻 塞 。 直 到 条 件 被
pthread_cond_signal 激发,该函数内部又会将锁状态恢复为锁定状态,最后再用
pthread_mutex_unlock 进行解锁。
注意 3:
pthread_cond_wait() 和 pthread_cond_timedwait()都被实现为取消点,也就是说如果
pthread_cond_wait()被取消,则退出阻塞,然后将锁状态恢复,然后当前线程就会终止。即
互斥锁又恢复锁定状态,然而当前线程已经被取消掉,那么这个互斥锁就不会被解开了,此
时锁得不到释放,就会造成死锁,因而需要在线程退出前为其解锁。
(5)示例
1.初始化条件变量和互斥锁
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
2.在线程中使用
(1)生产者线程
pthread_mutex_lock(&mutex);// 使用互斥锁保护共享数据
对缓冲区buffer写入操作
pthread_cond_signal(&cond);// 通知阻塞的消费者线程,数据写入完毕,可以解除阻塞了
pthread_mutex_unlock(&mutex);
(2)消费者线程
pthread_mutex_lock(&mutex); //调用pthread_cond_wait前一般都会搭配pthread_mutex_lock
pthread_cond_wait(&cond, &mutex); //等待生产者线程的通知
从缓冲区buffer中读出数据
pthread_mutex_unlock(&mutex); //解锁
3.销毁条件变量和互斥锁
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
本文参考文章:
https://www.cnblogs.com/hesper/p/10738996.html
https://www.cnblogs.com/harlanc/p/8596211.html