互斥锁和条件变量是痛不的基本组成部分。如果一个互斥锁或者条件变量存放在多个进程间共享的某个内存区域中,那么POSIX还允许它用于这些进程间的同步。(
互斥锁是协作性的锁)
1:上锁与解锁
互斥锁:指的是相互排斥的锁,用于保护临界区,保证任何时刻只有一个线程/进程在执行其中的代码。即保证了任何时刻只有一个线程在执行其临界区的指令。
用于给互斥锁上锁和解锁函数:
- #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);
对于一个已经由另外的线程上锁的互斥锁上锁,pthread_mutex_lock则会被阻塞到该互斥锁解锁为止,Pthread_mutex_trylock对应的是非阻塞函数,如果互斥锁已经存在,就返回一个EBUSY错误。
互斥锁实际为了保护临界去中被操纵的数据。互斥锁通常用于保护由多个线程或者多个进程共享的共享数据。
2:生产者与消费者的问题:
有两种情况,一种是先只关心生产者,等到所有生产者线程都完成工作后,我们才启动消费者线程。 一种是在所有生产者线程都启动后立即启动消费者线程。这样在生产者线程产生数据的同时,消费者线程就处理它。
不同指出:
这个是第一种,它是一直等到所有生产者线程种植后,同时输出每个线程的计数器,此后才启动单个消费者
- for(i=0;i<nthread;i++)
- {
- count[i]=0;
- pthread_create(&tid_produce[i],NULL,produce,&count[i]);
- }
- for(i=0;i<nthread;i++)
- {
- pthread_join(tid_produce[i],NULL);
- printf("count[%d]=%d\n",i,count[i]);
- }
- pthread_create(&tid_consume,NULL,consume,NULL);
- pthread_join(tid_consume,NULL);
第二种,它在生产者产生数据的同时,消费者就处理它。
- for(i=0;i
- {
- count[i]=0;
- pthread_create(&tid_produce[i],NULL,produce,&count[i]);
- }
- pthread_create(&tid_consume,NULL,consume,NULL);
- for(i=0;i
- {
- pthread_join(tid_produce[i],NULL);
- printf("count[%d]=%d\n",i,count[i]);
- }
- pthread_join(tid_consume,NULL);
2:条件变量:等待与信号发送
互斥锁用于上锁,条件变量则用于等待。
- #include<pthread>
- int pthread_cond_wait(pthread_cond_t *cptr,pthread_mutex_t *mptr);
- int pthread_cond_signal(pthread_cond_t *cptr);
一般情况下 我们在使用条件变量的时候,仍然需要互斥锁的配合,例如我们将互斥锁与条件变量放在一个结构体。
- struct
- {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- int nready;//number ready for consumer
- }nready={PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER};
3:避免上锁冲突
当条件变量被发送信号后,系统立即调用等待在其上的线程,该线程开始运行,但立即停止,因为它不能获得相应的互斥锁。如下:
- 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\n",i,buff[i]);
- }
- return NULL;
- }
更改后为:
- int dos;
- pthread_mutex_lock(&nready.mutex);
- dos=(nready.nready==0);
- nread.nready++;
- pthread_mutex_unlock(&nready.mutex);
- if(dos)
- pthread_cond_signal(&nready.cond);
4:条件变量:定时等待和广播
pthread_cond_signal()置换醒等待在条件变量上的一个线程,而pthread_cond_broadcast唤醒阻塞在相应条件变量上的所有线程。
- #include<pthread.h>
- int pthread_cond_broadcast(pthread_cond_t *cptr);
- pthread_cond_timedwait(pthread_cond_t *cptr,pthread_mutex_t *mptr,const struct timespec *abstime);
- struct timespec
- {
- time_t tv_sec;
- long tv_nsec;
- };
时间值是绝对时间。
5:互斥锁和条件变量的属性
- #include<pthread.h>
- int pthread_mutex_init(pthread_mutex_t *mptr,const pthread_mutexattr_t *attr);
- int pthread_mutex_destroy(pthread_mutex_t *mptr);
- int pthread_cond_init(pthread_cond_t *cptr,const pthread_condattr_t *attr);
- int pthread_cond_destroy(pthread_cond_t *cptr);
- int pthread_mutexattr_init(pthread_mutexattr_t *attr);
- int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
- int pthread_condattr_init(pthread_condattr_t *attr);
- int pthread_condattr_destroy(pthread_condattr *attr);
互斥锁属性对象或者条件变量属性对量被初始化。
制定互斥锁或者条件变量在不同进程间共享,而不是只在单个进程内的不同线程共享,这个属性是永以下函数
- #include<pthread.h>
- int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr,int *valptr);
- int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int value);
- pthread_condattr_getshared(pthread_condattr_t *attr,int valptr);
- int pthread_condattr_setpshared(pthread_condattr_t *attr,int value);
6:持有锁期间进程终止?
一个线程也可以在持有某个互斥锁期间终止,起因是被另一个线程取消或者自己去调用了pthread_exit.
如果是被另一个线程取消的情况,那么该线程可以安装将在被取消时调用的清理处理程序。
阅读(2142) | 评论(0) | 转发(0) |