Linux线程同步机制二--条件变量cond

来源:互联网 发布:js做一个弹窗 编辑:程序博客网 时间:2024/05/17 07:10

一、条件变量基本原理

  条件变量可以使线程睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

二、条件变量操作流程

  1.定义互斥锁、条件变量
  2.初始化互斥锁、条件变量;
  3.创建线程;
  4.条件不成立,线程进入睡眠状态;
  5.另一线程在条件成立是唤醒睡眠的线程(可能不止一个线程);
  6.线程退出,释放资源(销毁互斥锁、条件变量)。

三、条件变量基本操作函数

  互斥锁基本操作函数如下表所示:
 这里写图片描述

1.初始化条件变量
  在使用条件变量前,需要定义该条件变量(全局变量),定义条件变量代码如下:

pthread_cond_t condtion

  pthread_cond_init()函数用来初始化条件变量,其函数申明如下:

int pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t* cond_attr);

  第1个参数cond指向要初始化的条件变量指针;
  第2个参数cond_attr指向属性对象的指针,该属性对象定义要初始化的条件变量的特性,如果该指针为NULL,则使用默认的属性。下面是一段初始化条件变量的代码:

pthread_cond_t cv;pthread_condattr_t cattr;int ret;ret = pthread_cond_init(&cv, NULL);      // 使用默认属性初始化条件变量ret = pthread_cond_init(&cv, &cattr);    // 使用自定义属性初始化条件变量

  函数执行成功时返回0。否则,返回错误编码号以指明错误。

2.等待条件变量
  pthread_cond_wait()函数阻塞等待某个条件变量,其函数声明如下:

int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);

  第1个参数cond是指向要等待的条件变量的指针;
  第2个参数mutex是指向与条件变量cond关联的互斥锁的指针。

  pthread_cond_timedwait()函数阻塞等待某个条件变量,其函数声明如下:

int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex, struct timespec* abstime);

  第1个参数cond是指向要等待的条件变量的指针;
  第2个参数mutex是指向与条件变量cond关联的互斥锁的指针。
  第3个参数abstime是等待过期的绝对时间,该时间为从1970-1-1:0:0:0以来的秒数,即为一个绝对时间。该数据结构声明如下:

struct timespec {    long ts_sec;    long ts_nsec;};

  两函数执行成功时返回0。否则,返回错误编码号以指明错误。

3.通知等待条件变量的线程
  pthread_cond_signal()函数用来通知等待条件变量的第一个线程。pthread_cond_broadcast()函数用来通知等待条件变量的所以线程。两函数的声明如下:

int pthread_cond_signal(pthread_cond_t* cond);int pthread_cond_broadcast(pthread_cond_t* cond);

  参数cond是指向要通知或者广播的条件变量的指针。
  两函数执行成功时返回0。否则,返回错误编码号以指明错误。

4.条件变量销毁
  pthread_cond_destroy()函数用来销毁条件变量,其函数申明如下:

int pthread_cond_destroy(pthread_cond_t* cond);

  参数cond指向要销毁的条件变量的指针。
  函数执行成功时返回0。否则,返回错误编码号以指明错误。

四、条件变量常规操作

  下面给出条件变量常规操作:

#include <pthread.h>static pthread_mutex_t mutex;  /*互斥锁*/static pthread_cond_t cond;    /*条件变量*//*** 初始化条件变量*/void init_cond(void){    pthread_mutex_init(&mutex, NULL);    pthread_cond_init(&cond, NULL);    return;}/*** 销毁条件变量*/void destroy_cond(void){    pthread_mutex_destroy(&mutex);    pthread_cond_destroy(&cond);    return;}/*** 获取条件变量,使当前线程进入睡眠状态*/void get_cond(void){    pthread_mutex_lock(&mutex);    pthread_cond_wait(&cond, &mutex);   /*等待*/    pthread_mutex_unlock(&mutex);    return;}/*** 唤醒等待条件变量进入睡眠的线程*/void wakeup_cond(void){    pthread_mutex_lock(&mutex);     /*锁住互斥锁*/    pthread_cond_signal(&cond);     /*条件改变,发送信号*/    pthread_mutex_unlock(&mutex);   /*解锁互斥锁*/    return;}

五、示例

  初始状态有i=3, j=7,A线程执行i++; j--;操作。B线程只有在i == j时执行do_somethind();函数,下面通过条件变量来解决此问题:

#include <stdio.h>  #include <pthread.h>int i = 3;int j = 7;static pthread_mutex_t mutex;  /*互斥锁*/static pthread_cond_t cond;    /*条件变量*//*** 初始化条件变量*/void init_cond(void){    pthread_mutex_init(&mutex, NULL);    pthread_cond_init(&cond, NULL);    return;}/*** 释放条件变量*/void destroy_cond(void){    pthread_mutex_destroy(&mutex);    pthread_cond_destroy(&cond);    return;}/*** 获取条件变量,使当前线程进入睡眠状态*/void get_cond(void){    pthread_mutex_lock(&mutex);    pthread_cond_wait(&cond, &mutex);   /*等待*/    pthread_mutex_unlock(&mutex);    return;}/*** 唤醒等待条件变量进入睡眠的线程*/void wakeup_cond(void){    pthread_mutex_lock(&mutex);     /*锁住互斥锁*/    pthread_cond_signal(&cond);     /*条件改变,发送信号*/    pthread_mutex_unlock(&mutex);   /*解锁互斥锁*/    return;}void do_something(){    printf("I am doing something ...\n");}void* pth_A(void* arg){    while (1) {        if (i == j) {            printf("pthread A wakeup_cond()\n");            wakeup_cond();            break;        }        i++;        j--;        sleep(1);    }    pthread_exit(0);}void* pth_B(void* arg){    while (1) {        if (i != j) {            printf("pthread B get_cond()\n");            get_cond();        }        if (i == j) {            do_something();            break;        }    }    pthread_exit(0);}int main()  {      pthread_t tida, tidb;    int ret;    // 初始化锁    init_cond();    ret = pthread_create(&tida, NULL, pth_A, NULL);    if (0 != ret) {        perror("create pthead error");        return -1;    }    ret = pthread_create(&tidb, NULL, pth_B, NULL);    if (0 != ret) {        perror("create pthead error");        return -1;    }    pthread_join(tida, NULL);    pthread_join(tidb, NULL);    // 销毁锁    destroy_cond();    return 0;}

运行结果如下所示:
这里写图片描述

  如上图所示线程B获得CPU资源时条件不成立,进入休眠状态,当线程A执行到i == j时便唤醒B线程。B线程被唤醒时条件成立,便调用了函数do_something()

原创粉丝点击