作用
互斥锁用于确保关键资源在修改时只有一个操作者
条件变量类似银行的叫号,协调各个操作者的操作顺序.当前一个操作者操作完成时,叫正在等待的下一个操作者前来操作.
在不引入条件变量之前,互斥锁会使其它线程处于空等状态,不断进行锁状态的检查.条件变量引入后,使相关的其它线程处于睡眠状态,当前操作者完成操作后再唤醒处于睡眠状态的线程.
基本函数
#include <pthread.h>
//互斥锁
int pthread_mutex_lock(pthread_mutex_t *mptr);
int pthread_mutex_trylock(pthread_mutex_t *mptr);
int pthread_mutex_unlock(pthread_mutex_t *mptr);
//条件变量
int pthread_cont_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
int pthread_cont_signal(pthread_cond_t *cptr);
//初始化与销毁
int pthread_mutex_init(pthread_mutex_t *mptr,const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mptr);
PTHREAD_MUTEX_INITIALIZER
int pthread_cond_init(pthread_cond_t *cptr,const pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cptr);
PTHREAD_COND_INITIALIZER
例子
创建<#nthreads>个tid_produce线程, 生产<#nitems>个产品,每个线程生产出一个就通知consume线程
每个线程生产的总数记录在count[i]中, put结构中的nput记录当前所有线程已经生产的总数
#include "unpipc.h"
#include <pthread.h>
#define MAXITEMS 1000000
#define MAXTHREADS 100
#define min(a,b) a>b?b:a
int nitems;
int buff[MAXITEMS];
struct {
pthread_mutex_t mutex;
int nput;
int nval;
} put= {
PTHREAD_MUTEX_INITIALIZER
};
struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
int nready;
} nready= {
PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER
};
void *produce(void *), *consume(void *);
int main(int argc, char *argv[]){
int i,nthreads,count[MAXTHREADS];
pthread_t tid_produce[MAXTHREADS],tid_consume;
if(argc != 3)
err_quit("usage: lock <#items> <#threads>");
nitems=min(atoi(argv[1]),MAXITEMS);
nthreads=min(atoi(argv[2]),MAXTHREADS);
pthread_setconcurrency(nthreads+1);
pthread_create(&tid_consume,NULL,consume,NULL);
for(i=0;i<nthreads;++i){
count[i]=0;
pthread_create(&tid_produce[i],NULL,produce,&count[i]);
}
for(i=0;i<nthreads;++i){
pthread_join(tid_produce[i],NULL);
printf("in main: count[%d]=%d
",i,count[i]);
}
pthread_join(tid_consume,NULL);
return 0;
}
void *
produce(void *arg){
for(;;){
pthread_mutex_lock(&put.mutex);
if(put.nput >= nitems){
pthread_mutex_unlock(&put.mutex);
return(NULL);
}
buff[put.nput] = put.nval;
put.nput++;
put.nval++;
pthread_mutex_unlock(&put.mutex);
pthread_mutex_lock(&nready.mutex);
if(nready.nready == 0)
pthread_cond_signal(&nready.cond);
nready.nready++;
pthread_mutex_unlock(&nready.mutex);
*((int *)arg) += 1; //count[i] += 1
}
}
void *
consume(void *arg){
int i;
for(i=0;i<nitems;++i){
pthread_mutex_lock(&nready.mutex);
while(nready.nready == 0)
pthread_cond_wait(&nready.cond,&nready.mutex);
nready.nready--;
pthread_mutex_unlock(&nready.mutex);
if(buff[i] != i)
printf("buff[%d] = %d
",i,buff[i]);
}
return NULL;
}