Pthread提供许多可以用来同步线程的函数。其基本机制是使用一个可以被锁定和解锁的互斥量来保护每个临界区。一个线程如果想要进入临界区,它首先尝试锁住相关的互斥量。如果互斥量没有加锁,那么这个线程可以立即进入,并且该互斥量被自动锁定以防止其他线程进入。如果互斥量已经被加锁,则调用线程被阻塞,直到该互斥量被解锁。
……
除互斥量外,pthread提供了另一种同步机制:条件变量。互斥量在允许或阻塞对临界区的访问上是很有用的,条件变量则允许线程由于一些未达到的条件而阻塞。
/**
* 代码中增加一些输出语句方便观察代码的执行
*/
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#define MAX 1000000000 //需要生产的数量
pthread_mutex_t the_mutex; //互斥量
pthread_cond_t condc,condp;
int buffer=1; //生产者消费者使用的缓冲区
int step=0;
//生产数据
void *producer(void *ptr)
{
int i;
for(i=1;i<=MAX;i++)
{
printf("producer step %d\n",step++);
pthread_mutex_lock(&the_mutex); //互斥使用缓冲区
printf("producer before %d %d\n",i,buffer);
/**
* 这里需要特别注意pthread_cond_wait这个函数
* 这个函数实际上做了两件事情:
* 1.让生产者线程进入阻塞状态
* 2.解锁the_mutex这个互斥量,这时候消费者线程就可以获得the_mutex并执行
* 3.这两个操作应该是原子操作,否则的话如果对condp加锁的话,生产者线程进入阻塞状态,the_mutex就不能解锁了;而如果先对the_mutex进行解锁,那又可能出现多个线程对condp的竞争。(个人猜测)
* 4.这个地方我测试的时候将the_mutex修改成一个无关的互斥量,然后消费者进程不能执行。这说明了在pthread_condp中是有对the_mutex解锁的操作的。只是不太清楚这里的解锁和pthread_mutex_unlock的解锁有什么不同。
*/
while(buffer!=0)pthread_cond_wait(&condp,&the_mutex);
printf("producer %d %d\n",i,buffer);
buffer=i; //将数据放入缓冲区
pthread_cond_signal(&condc); //唤醒消费者
pthread_mutex_unlock(&the_mutex); //释放缓冲区
}
pthread_exit(0);
}
//消费数据
void *consumer(void *ptr) //消费数据
{
int i;
for(i=1;i<=MAX;i++)
{
printf("comsumer step %d\n",step++);
pthread_mutex_lock(&the_mutex); //互斥使用缓冲区
printf("consumer before %d %d\n",i,buffer);
while(buffer==0) pthread_cond_wait(&condc,&the_mutex);
printf("consumer %d %d\n",i,buffer);
buffer=0; //从缓冲区中取出数据
pthread_cond_signal(&condp); //唤醒生产者
pthread_mutex_unlock(&the_mutex); //释放缓冲区
}
pthread_exit(0);
}
int main(int argc,char **argv)
{
pthread_t pro,con;
pthread_mutex_init(&the_mutex,0); //初始化一个互斥量
pthread_cond_init(&condc,0); //初始化一个条件变量
pthread_cond_init(&condp,0); //初始化一个条件变量
pthread_create(&con,0,consumer,0); //创建一个新线程,新线程调用consumer
pthread_create(&pro,0,producer,0); //创建一个新线程,新线程调用producer
pthread_join(pro,0); //等待pro线程退出
pthread_join(con,0); //等到con线程退出
printf("over\n");
pthread_cond_destroy(&condc); //撤销条件变量
pthread_cond_destroy(&condp); //撤销条件变量
pthread_mutex_destroy(&the_mutex); //撤销互斥量
return 0;
}