条件变量pthread_cond_t

条件变量是什么

条件变量是线程同步的一种手段,用于阻塞线程直到条件发生。

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个/多个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"信号。

代码示例:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
    pthread_t t_a;
    pthread_t t_b;
    pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/
    pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/
    pthread_join(t_a, NULL);/*等待进程t_a结束*/
    pthread_join(t_b, NULL);/*等待进程t_b结束*/
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    exit(0);
}
void *thread1(void *junk)
{
    for(i=1;i<=6;i++)
    {
        pthread_mutex_lock(&mutex);/*锁住互斥量*/
		printf("thread1: lock %d/n", __LINE__);
        if(i%3==0){
			printf("thread1:signal 1  %d/n", __LINE__);
            pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
			printf("thread1:signal 2  %d/n", __LINE__);
			sleep(1);
		}
        pthread_mutex_unlock(&mutex);/*解锁互斥量*/
		printf("thread1: unlock %d/n/n", __LINE__);
		sleep(1);
	}
}
void *thread2(void *junk)
{
    while(i<6)
    {
        pthread_mutex_lock(&mutex);
		printf("thread2: lock %d/n", __LINE__);
		if(i%3!=0){
			printf("thread2: wait 1  %d/n", __LINE__);
            pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变*/
			printf("thread2: wait 2  %d/n", __LINE__);
		}
        pthread_mutex_unlock(&mutex);
		printf("thread2: unlock %d/n/n", __LINE__);
		sleep(1);
	}
}

gcc thread_cond.c -lpthread -o tcd

输出:

tcd--

pthread_cond_wait (&cond,&mutex);
这里的线程二阻塞,不仅仅是等待cond变量发生改变,同时释放mutex锁。

不过此时线程二并没有立即得到运行 ,因为线程二还在等待mutex锁的释放。

如果需要读取某条件,需要与while一起工作

pthread_cond_wait返回,并不一定意味着当前的线程等待的条件成立,因为有Spurious wakeup现象,详见 http://vladimir_prus.blogspot.com/2005/07/spurious-wakeups.html 。

简单来说就是Linux中带阻塞功能的system call都会在进程收到了一个signal后返回。

mutex和singal的顺序问题

因为需要配合使用,所以有以下两种顺序选择:

  1. 先unlock,然后condition_signal。当等待线程被唤醒时,可以直接锁住mutex然后从condition_wait中返回。
  2. 先condition_signal,然后unlock,当等待线程被唤醒时,试图锁住mutex但是不成功,继续休眠,知道mutex成功解锁后,线程又再次被唤醒并锁住mutex,然后从condition_wait中返回。

顺序2的情况,线程切换的次数较多;但是顺序1的情况,先unlock,mutex可能会被其他线程获取,继而修改其他变量。所以顺序2比较严谨。

comments powered by Disqus