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

一、条件变量基本原理

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

二、条件变量操作流程

  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()

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值