【linux高级程序设计】(第十二章)Linux多线程编程 3

条件变量通信机制

条件变量必须配合互斥锁一起实现对资源的互斥访问

使用方法:

int pthread_cond_init (pthread_cond_t *__restrict __cond, __const pthread_condattr_t *__restrict __cond_attr) :初始化条件变量,第二个参数是属性对象,NULL为默认

int pthread_cond_destroy (pthread_cond_t *__cond)销毁条件变量

int pthread_cond_signal (pthread_cond_t *__cond)通知等待条件变量的第一个线程,如果没有等待线程,则不起作用

int pthread_cond_broadcast (pthread_cond_t *__cond)通知等待的条件变量的所有线程,如果没有等待线程,则不起作用

int pthread_cond_wait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex)等待条件变量,第二个参数指向于条件变量关联的互斥锁指针

int pthread_cond_timewait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex, __const struct timespec *__restrict __abstime) :在指定时间内等待条件变量

在线程因等待条件变量进入等待状态时,将释放其申请的互斥锁。在等到条件变量时,会隐含申请到该互斥锁              

条件变量实现读写锁

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include "pthread.h"
#define BUFFER_SIZE 2
//条件信息结构体
struct prodcons
{
    int buffer[BUFFER_SIZE];  //生产产品值
    pthread_mutex_t lock;     //互斥锁
    int readpos, writepos;    //读写位置
    pthread_cond_t notempty;  //条件变量,表非空
    pthread_cond_t notfull;   //条件变量,表非满
};

//初始化
void init(struct prodcons *prod)
{
    pthread_mutex_init(&prod->lock, NULL);
    pthread_cond_init(&prod->notempty, NULL);
    pthread_cond_init(&prod->notfull, NULL);
    prod->readpos = 0;
    prod->writepos = 0;
}

//在缓冲区输入一个数据
void put(struct prodcons * prod, int data)
{
    //锁定互斥锁
    pthread_mutex_lock(&prod->lock);
    while((prod->writepos + 1) % BUFFER_SIZE == prod->readpos) //测试是否空间已满  注意 这里writepos的位置要加1 即保证下一个写入的位置是空的 ??
    {
        printf("producer wait for not full
");
        pthread_cond_wait(&prod->notfull, &prod->lock); //等待有空间写
    }
    //写数据
    prod->buffer[prod->writepos] = data;
    prod->writepos++;
    if(prod->writepos >= BUFFER_SIZE)
        prod->writepos = 0;
    pthread_cond_signal(&prod->notempty);
    pthread_mutex_unlock(&prod->lock);
}

//从缓冲区读一个数据
int get(struct prodcons * prod)
{
    int data;
    //锁定互斥锁
    pthread_mutex_lock(&prod->lock);
    while(prod->writepos == prod->readpos)
    {
        printf("producer wait for not empty
");
        pthread_cond_wait(&prod->notempty, &prod->lock); 
    }
    data = prod->buffer[prod->readpos];
    prod->readpos++;
    if(prod->readpos >= BUFFER_SIZE)
        prod->readpos = 0;
    pthread_cond_signal(&prod->notfull);
    pthread_mutex_unlock(&prod->lock);
    return data;
}

#define OVER (-1)
struct prodcons buffer;

//生产者
void * producer(void * data)
{
    int n;
    for(n = 1; n <= 5; n++) //生产5个产品
    {
        printf("producer sleep 1 second...
");
        sleep(1);
        printf("put the %d product
", n);
        put(&buffer, n);
    }
    for(n = 6; n <= 10; n++)
    {
        printf("producer sleep 3 second...
");
        sleep(3);
        printf("put the %d product
", n);
        put(&buffer, n);
    }
    put(&buffer, OVER);
    printf("producer stopped!
");
    return NULL;
}

//消费者
void * consumer(void * data)
{
    int d = 0;
    while(1)
    {
        printf("consumer sleep 2 second...
");
        sleep(2);
        d = get(&buffer);
        printf("get the %d product
", d);
        if(d == OVER)
            break;
    }
    printf("consumer stopped!
");
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t th_a, th_b;
    void * retval;
    init(&buffer);
    pthread_create(&th_a, NULL, producer, 0);
    pthread_create(&th_b, NULL, consumer, 0);
    pthread_join(th_a, &retval);
    pthread_join(th_b, &retval);
    return 0;
}

验证,可用

原文地址:https://www.cnblogs.com/dplearning/p/4690466.html