线程-条件变量(实现生产者和消费者问题)

条件变量不是锁,但是条件变量能够阻塞线程

通常和互斥量一起使用:互斥量用来保护一段共享数据,而条件变量用来引起阻塞

条件变量的俩个动作:

当条件不满足时,阻塞线程

当条件满足,通知阻塞的线程开始工作


主要函数 

条件变量的类型:

Pthread_cond_t cond;

初始化一个条件变量--condtion

Pthread_cond_init(

         Pthread_cond_t*restrict cond,

         Constpthread_condattr_t *restrict attr

);

销毁一个条件变量

Pthread_cond_destroy(pthread_cont_t *cond);

阻塞一个条件变量

Pthread_cond_wait( pthread_cond_t *restrictcond,pthread_mutex_t *restrict mutex);

限时等待一个条件变量

Pthread_cond_timedwait(

         Pthread_cond_t*restrict cond,

         Pthread_mutex_trestrict mutex,

         Conststruct timespec *restrict abstime

);

唤醒至少一个阻塞在条件变量上的线程

Pthread_cond_signal(pthread_cond_t *cond);

唤醒全部阻塞在条件变量上的线程

Pthread_cond_broadcast(pthread_cond_t*cond);

解决生产者和消费者问题

如烧饼问题,生产者在一直的生产烧饼,而消费者不断的消费烧饼,如果烧饼没有了,则消费者会等待生产者生产,生产过后会通知消费者进行消费

其中mutex的值的会发生改变 

加入消费者开始消费,此时mutex值为1,当pthread_mutex_lock加锁后,mutex值变为0,如果没有烧饼,执行pthread_cond_wait发生阻塞,因为这个函数中也有mutex参数,此时将mutex值变为1,相当于解锁,那么生产者就会加锁成功,开始生产,生产后,pthread_mytex_unlock会使mutex值变为1,执行pthread_cond_signal函数,这个函数会唤醒阻塞在条件变量上的线程,也就是pthread_cond_wait此时解除了阻塞,同时加锁,mutex变为0

用无头节点的链表来实现生产者消费者问题(生产用头插法,消费用头删法)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
//节点结构
typedef struct node
{
    int data;
    struct node *next;
}Node;
//永远指向链表头部的指针
Node *head=NULL;
//生产者
//线程同步--互斥锁
pthread_mutex_t mutex;
//阻塞线程--条件变量类型的变量
pthread_cond_t cond;
void *producer(void *sig)
{
    while(1)
    {
        //创建一个链表的节点
        Node *pnew=(Node *)malloc(sizeof(malloc));
        //节点的初始化
        pnew->data=rand()%1000;  //0-999
        //使用互斥锁保护共享数据
        pthread_mutex_lock(&mutex);
        //指针域
        pnew->next=head;
        head=pnew;
        printf("===== produce:%x,%d\n",(unsigned int)pthread_self(),pnew->data);
        //解锁
        pthread_mutex_unlock(&mutex);
        //通知阻塞x的消费者线程,解除阻塞
        pthread_cond_signal(&cond);
        sleep(rand()%3);
    }
    return NULL;
}
void *customer(void *arg)
{
    while(1)
    {
        //加锁
        pthread_mutex_lock(&mutex);
        if(head==NULL)
        {
            //线程阻塞
            //该函数会对互斥锁进行解锁
            pthread_cond_wait(&cond,&mutex);
            //解除阻塞后,会对互斥锁做加锁操作
        }
        //链表不为空,删掉一个节点,删除头节点  <当作消费者>
       Node *pdel=head;
       head=head->next;
       printf("-----customer %x ,%d\n",(unsigned int)pthread_self(),pdel->data);
       free(pdel);
       //解锁
       pthread_mutex_unlock(&mutex);
    }
    return NULL;
}
int main()
{
    //初始化
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_t p1,p2;
    //创建生产者线程
    pthread_create(&p1,NULL,producer,NULL);
    //创建消费者线程
    pthread_create(&p2,NULL,customer,NULL);
    //阻塞回收d子线程
    pthread_join(p1,NULL);
    pthread_join(p2,NULL);
    //销毁
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

可以看出生产者和消费者之间的一个同步





猜你喜欢

转载自blog.csdn.net/qq_38635597/article/details/80045817
今日推荐