【Linux多线程编程-自学记录】10.条件变量

Linux多线程编程学习代码(代码已上传gitee,还请各位兄弟点个Star哦!)

https://gitee.com/chenshao777/linux_thread.git


笔记:
1.条件变量引入
需要一种机制,当互斥量被锁柱后,发现当前线程还是无法完成自己的操作
那么它应该自己释放互斥量,让其他线程得以工作

方法1:采用轮询方式
方法2:让系统查询条件,使用系统条件变量 pthread_cond_t cond

2.条件变量初始化和销毁
条件变量使用之前需要初始化
1、pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
2、int pthread_cond_init(pthread_cond_t *restrict cond,
                      const pthread_condattr_t *restrict attr)
第一个参数是条件变量
第二个参数默认属性为空NULL
条件变量使用完成之后需要销毁
int pthread_cond_destroy(pthread_cond_t *cond);

3.条件变量的使用
条件变量使用雷要配合互斥量
int pthread_cond_wait(pthread_cond_t *restrict cond.
pthread_mutex_t *restrict mutex);
1、使用pthread_cond_wait等待条件变为真。传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传递给函数。
2、这个函数将线程放到等待条件的线程列表上,然后对互斥量进行解锁,这是个原子操作。当条件满足时这个函数返回,返回以后维续对互斥量加锁。
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
3、这个函数与pthread_cond_wait类似,只是多一个timeout,如果到了指定的时间条件还不满足,那么就返回。
时间用下面的结构体表示
struct timespec{
time_t tv_sec;
long tv_nsec;
}:
注意。这个时间是绝对时间。例如你要等待3分钟,就要把当前时间加上3分钟然后转换到timespec·而不是直接将3分钟转换到timespec

当条件满足的时候,需要唤醒等侍条件的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
Iint pthread_cond_signal(pthread_cond_t *cond);
1、pthread_cond_broadcast 唤醒等待条件的所有线程(广播)
2、pthread_cond_signal 至少唤醒等待条件的某一个线程
注意,一定要在条件改变以后在唤醒线程


spu.h文件

#ifndef _SPU_H_
#define _SPU_H_

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>
#include<errno.h>

#endif

10.thread_cond.c文件

/*
  1.创建一个生产者,两个消费者
  2.生产者0.5秒生产一个产品,并且发送条件变量广播唤醒等待的线程
  3.消费者1秒消费一个产品
  4.条件变量要配合互斥锁
*/

#include "spu.h"
#include <time.h>

/*产品结构体*/
typedef struct product{
    
    
    int num;
    struct product *next;  //指向下一个产品
}product_t;

/*定义第一个产品:链表首节点*/
product_t *head = NULL;

/*初始化互斥锁*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  //使用宏定义初始化互斥锁
/*初始化条件变量*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;     //使用宏定义初始化条件变量

/*
  生产者线程
*/
void *thread_product(void *arg)
{
    
    
    for(;;)
    {
    
    
        //申请一个新的节点
        product_t *p = (product_t*)malloc(sizeof(product_t));
        p->num = rand() % 100 + 1;  //生成 1-100 之间的随机数

        //加锁
        pthread_mutex_lock(&mutex);
        
        //向链表表头加节点
        p->next = head;
        head = p;
        printf("生产者:%d\n",head->num);

        //解锁
        pthread_mutex_unlock(&mutex);
        //通知所有/单个消费者
        pthread_cond_broadcast(&cond);
        
        usleep(500000);
    }
}

/*
  消费者线程1
*/
void *thread_consume01(void *arg)
{
    
    
    for(;;)
    {
    
    
        //加锁
        pthread_mutex_lock(&mutex);

        //如果没有产品则等待
        if(head->next == NULL)
          //等待被通知,如果无通知,则自解锁(通过第二个参数),进入阻塞状态,等待被系统唤醒
          pthread_cond_wait(&cond, &mutex);
        //得到通知,开始消费
        printf("消费者1:%d\n", head->num);
        head = head->next;

        //解锁
        pthread_mutex_unlock(&mutex);
        usleep(1000000);

    }
}

/*
  消费者线程2
*/
void *thread_consume02(void *arg)
{
    
    
    for(;;)
    {
    
    
        //加锁
        pthread_mutex_lock(&mutex);

        //如果没有产品则等待
        if(head->next == NULL)
          //等待被通知,如果无通知,则自解锁(通过第二个参数),进入阻塞状态,等待被系统唤醒
          pthread_cond_wait(&cond, &mutex);
        //得到通知,开始消费
        printf("消费者2:%d\n", head->num);
        head = head->next;

        //解锁
        pthread_mutex_unlock(&mutex);
        usleep(1000000);

    }
}

int main()
{
    
    
    srand((unsigned int)time(NULL));  //设置随机种子          
    pthread_t pro_pid, con_pid1, con_pid2;
    void *_return1,*_return2,*_return3;

    /*创建生产者线程*/
    pthread_create(&pro_pid, NULL, thread_product, NULL);
    /*创建消费者线程1*/
    pthread_create(&con_pid1, NULL, thread_consume01, NULL);
    /*创建消费者线程2*/
    pthread_create(&con_pid2, NULL, thread_consume02, NULL);


    /*等待线程结束*/
    pthread_join(pro_pid,_return1);
    pthread_join(con_pid1,_return2);
    pthread_join(con_pid2,_return3);

    /*销毁互斥量*/
    pthread_mutex_destroy(&mutex);
    /*销毁条件变量*/
    pthread_cond_destroy(&cond);
}

猜你喜欢

转载自blog.csdn.net/HuangChen666/article/details/130464870