使用互斥锁可实现线程间数据的共享和通信,互斥锁的一个明显的缺点是它只有两种状态:锁定和非锁定。二条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。
使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁屏重新测试条件是否满足。
一个简单的例子
count为0时,decrement_count中的pthread_cond_wait处被阻塞,并解锁count_lock。此时,当调用到increment_count时,pthread_cond_signal改变条件变量,告知decrement_count停止阻塞。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t count_nonzero = PTHREAD_COND_INITIALIZER;
int count = 0;
void decrement_count()
{
while(1)
{
pthread_mutex_lock(&count_lock);
while(count == 0)
// 该条件获得信号之前,该函数一直被阻塞
// 该函数会在被阻塞之前以原子方式释放互斥锁count_lock
// 并导致调用线程基于count_nonzero所指向的条件变量阻塞
// 在返回之前以原子方式再次获取该互斥锁
// 当该线程更改条件值时,另一个线程会针对条件变量发出信号
// 这种变化会导致所有等待该条件的线程解除阻塞并尝试再次获取互斥锁
// 唤醒的线程重新获取互斥锁并从pthread_cond_wait()返回之前,
// 条件可能会发生变化
// 建议使用的测试方法是,将条件检查编写为调用pthread_cond_wait()的while()循环
pthread_cond_wait(&count_nonzero, &count_lock);
count = count - 1;
printf("decrement: %d\n", count);
pthread_mutex_unlock(&count_lock);
sleep(1);
}
}
void increment_count()
{
while(1)
{
pthread_mutex_lock(&count_lock);
if(count == 0)
// 解除count_nonzero所指向的条件变量阻塞的线程
// 应在互斥锁的保护下修改相关条件
pthread_cond_signal(&count_nonzero);
count = count + 1;
printf("increment: %d\n", count);
pthread_mutex_unlock(&count_lock);
sleep(1);
}
}
int main()
{
pthread_t de, in;
pthread_create(&de, NULL, (void*)decrement_count, NULL);
pthread_create(&in, NULL, (void*)increment_count, NULL);
pthread_join(de, NULL);
pthread_join(in, NULL);
pthread_mutex_destroy(&count_lock);
pthread_cond_destroy(&count_nonzero); // 销毁条件变量状态
return 0;
}
1个生产者—1个消费者
需要互斥地访问内存
当内存满,生产者不能生产,生产者生产后,唤醒消费者
当内存空,消费者不能消费,消费者消费了产品后,唤醒生产者
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int count = 0;
int maxcount = 5;
pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t less = PTHREAD_COND_INITIALIZER;
pthread_cond_t more = PTHREAD_COND_INITIALIZER;
void producer()
{
while(1)
{
pthread_mutex_lock(&count_lock);
while(count > maxcount)
pthread_cond_wait(&less, &count_lock);
count = count + 1;
printf("producer: %d\n", count);
pthread_cond_signal(&more);
pthread_mutex_unlock(&count_lock);
usleep(1000);
}
}
void consumer()
{
while(1)
{
pthread_mutex_lock(&count_lock);
while(count <= 0)
pthread_cond_wait(&more, &count_lock);
count = count - 1;
printf("consumer: %d\n", count);
pthread_cond_signal(&less);
pthread_mutex_unlock(&count_lock);
usleep(1000);
}
}
int main()
{
pthread_t pro, con;
pthread_create(&pro, NULL, (void*)producer, NULL);
pthread_create(&con, NULL, (void*)consumer, NULL);
pthread_join(pro, NULL);
pthread_join(con, NULL);
pthread_mutex_destroy(&count_lock);
pthread_cond_destroy(&less);
pthread_cond_destroy(&more);
return 0;
}
参考
https://wenku.baidu.com/view/e5d90e40336c1eb91a375da8.html
多线程编程指南