linux条件变量pthread_cond_wait和pthread_cond_signal函数

本次分析linux中的条件变量,条件变量本身不是锁,但它也可以造成线程阻塞,通常与互斥锁配合使用,给多线程提供一个会合的场所。

1.条件变量主要应用函数:
1.1.pthread_cond_init函数
函数作用:
  初始化一个条件变量。

函数原型:

int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

函数参数:
  cond:条件变量
  attr:条件变量的属性,通常为默认值,传NULL即可
返回值:
  成功:返回0;
  失败:返回非0。
注意:
  也可以使用静态初始化的方法,初始化条件变量:
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

1.2.pthread_cond_destroy函数
函数作用:
  销毁一个条件变量。
函数原型:

int pthread_cond_destroy(pthread_cond_t *cond);

函数参数:
  cond:条件变量
返回值:
  成功:返回0;
  失败:返回非0。

1.3.pthread_cond_wait函数
函数作用:
  阻塞等待一个条件变量。
函数原型:

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

函数参数:
  cond:条件变量
  mutex:锁变量
返回值:
  成功:返回0;
  失败:返回非0。
注意:
1、阻塞等待条件变量cond(参1)满足
2、释放已掌握的互斥锁(解锁互斥量)相当于pthread_mutex_unlock(&mutex);
   1、2、两步为一个原子操作。
3、当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁pthread_mutex_lock(&mutex);

1.4.pthread_cond_timedwait函数
函数作用:
  限时等待一个条件变量。
函数原型:

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);

函数参数:
  cond:条件变量
  mutex:锁变量
  abstime:绝对时间。
返回值:
  成功:返回0;
  失败:返回非0。
注意:
对形参3的特别说明:
  参看man sem_timedwait函数,查看struct timespec结构体。
  struct timespec {
    time_t   tv_sec;  /* seconds / 秒
    long   tv_nsec;  /
nanosecondes*/ 纳秒
    };
  如:time(NULL)返回的就是绝对时间。而alarm(1)是相对时间,相对当前时间定时1秒钟。
  struct timespec t = {1, 0};
  pthread_cond_timedwait (&cond, &mutex, &t); //只能定时到 1970年1月1日 00:00:01秒(早已经过去)
正确用法:
  time_t cur = time(NULL); //获取当前时间。
  struct timespec t; //定义timespec 结构体变量t
  t.tv_sec = cur+1; //定时1秒
  pthread_cond_timedwait (&cond, &mutex, &t); //传参
  在setitimer函数时还有另外一种时间类型:
  struct timeval {
    time_t    tv_sec;   /* seconds / 秒
    suseconds_t   tv_usec;   /
microseconds */ 微秒
    };

1.5.pthread_cond_signal函数
函数作用:
  唤醒至少一个阻塞在条件变量上的线程。
函数原型:

int pthread_cond_signal(pthread_cond_t *cond);

函数参数:
  cond:条件变量
返回值:
  成功:返回0;
  失败:返回非0。

1.6.pthread_cond_broadcast函数
函数作用:
  唤醒全部阻塞在条件变量上的线程。
函数原型:
  int pthread_cond_broadcast(pthread_cond_t *cond);
函数参数:
  cond:条件变量。
返回值:
  成功:返回0;
  失败:返回非0。

2.生产者消费者条件变量模型
线程同步典型的案例即为生产者消费者模型,而借助条件变量来实现这一模型,是比较常见的一种方法。假定有两个线程,一个模拟生产者行为,一个模拟消费者行为。两个线程同时操作一个共享资源,生产向其中添加产品,消费者从中消费掉产品。

#include 
#include 
#include 
#include 

struct msg{
    int num;
    struct msg *next;
};
struct msg *head = NULL;
struct msg *mp = NULL;
//静态初始化锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
//生产者

void *producer(void *arg)
{
    while (1)
    {
        //生产一个结点
        mp = malloc(sizeof(struct msg));
        mp->num = rand() % 100;
        printf("producer: %d\n", mp->num);
        //上菜到链表
        pthread_mutex_lock(&mutex);
        mp->next = head;
        head = mp;
        pthread_mutex_unlock(&mutex);
        //唤醒消费者
        pthread_cond_signal(&has_product);
        sleep(1);
    }
    return NULL;
}
//消费者
void *consumer(void *arg)
{
    while (1) {
        //加锁
        pthread_mutex_lock(&mutex);
        while (head == NULL) {
            //等待被唤醒
            pthread_cond_wait(&has_product, &mutex);
        }
        //开始消费
        mp = head;
        head = mp->next;
        pthread_mutex_unlock(&mutex);
        printf("____consumer: %d\n", mp->num);
        free(mp);//释放内存
        mp = NULL;
        sleep(1);
    }
    return NULL;
}

int main(void)
{
    pthread_t ptid, ctid;
    //创建生产者线程
    pthread_create(&ptid, NULL, producer, NULL);
    //创建消费者线程
    pthread_create(&ctid, NULL, consumer, NULL);
    pthread_join(ptid, NULL);
    pthread_join(ctid, NULL);
    return 0;
}

你可能感兴趣的:(linux)