多线程的同步与互斥机制(生产者&消费者模型)

同步:所有线程以某种顺序依次访问临界资源。
同步机制的实现:条件变量—–是利用线程间共享的全局变量进行同步的机制。(一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”(给出条件成立信号)。为了防止竞争资源,条件变量总是和互斥锁结合使用)
为什么要实现同步机制呢?(为了防止竞争资源)
生产者消费者模型为例,首先我们需要了解什么是生产者消费者模型:(三种关系、两种角色、一个交易场所)
生产者—–生产者(互斥关系)
生产者—–消费者(同步与互斥关系)
消费者—–消费者(互斥关系)
交易场所—–链表
看下面的代码:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<pthread.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //mutex_lock
typedef struct _Node
{
    int _val;
    struct _Node *_next;
}Node,*pNode,**ppNode;
pNode _head= NULL;
pNode BuyNode(int val)
{
    pNode tmp = (pNode)malloc(sizeof(Node));
    if(tmp)
    {
        tmp->_val = val;
        tmp->_next = NULL;
        return tmp;
    }
    return NULL;
}
void Init_List(ppNode head)
{
    *head = BuyNode(0);
}
//void Init_List()
//{
//  _head = BuyNode(0);
//}
void Push(pNode head,int val)
{
    pNode tmp = BuyNode(val);
    tmp->_next = head->_next;
    head->_next = tmp;
}
int Pop(pNode head)
{
    if(!Is_Empty(head))
    {
        pNode tmp = head->_next;
        int val=tmp->_val;
        head->_next = tmp->_next;
        free(tmp);
        tmp = NULL;
        return val;
    }
    return -1;
}
int Is_Empty(pNode head)
{
    if(head->_next == NULL)
    {
        return 1;
    }
    return 0;
}
void Print_List(pNode head)
{
    pNode tmp = head->_next;
    while(NULL != tmp)
    {
        printf("%d  ",tmp->_val);
        tmp = tmp->_next;
    }
    printf("\n");
}
void* consumer(void* arg)
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        int val=Pop(_head);
        printf("consumer: %d\n",val);
        pthread_mutex_unlock(&lock);
    }
    return (void*)0;
}
void* producer(void* arg)
{
    while(1)
    {
        sleep(1);
        pthread_mutex_lock(&lock);
        int val = rand()%10000;
        Push(_head,val);
        printf("producer: %d\n",val);
        pthread_mutex_unlock(&lock);
    }
    return (void*)0;
}
int main()
{
    Init_List(&_head);//交易场所:链表
    //Init_List();
    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,consumer,NULL);
    pthread_create(&tid2,NULL,producer,NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_mutex_destroy(&lock);
    //Push(_head,1);
    //Push(_head,2);
    //Push(_head,3);
    //Push(_head,4);
    //Push(_head,5);
    //int val=Pop(_head);
    //printf("%d\n",val);
    //Print_List(_head);
    return 0;
}

这里写图片描述

在上面的代码中生产者的优先级低于消费者,导致消费者一直在获得锁读取链表的数据再释放锁,紧接着又获得了锁,使得生产者一直处于挂起状态,而我们想要的是生产者生产一个数据,消费者消费一个数据。此时就需要引入同步机制(条件变量)使得消费者和生产者依次来访问该链表从而达到生产—消费平衡。

条件变量的创建:
静态创建:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
动态创建:int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
参数1:条件变量cond的地址
参数2:条件变量cond的属性,设置为NULL
等待:
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);//在条件变量cond上阻塞式等待,这个函数做以下三步操作:
1. 释放Mutex
2. 阻塞等待
3. 当再次被唤醒时,自动获得Mutex
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);//条件变量cond上非阻塞式等待,参数3可以设定等待超时,如果到达了abstime所指定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。
唤醒:
int pthread_cond_signal(pthread_cond_t *cond)//唤醒在该cond上等待的另⼀个线程
int pthread_cond_broadcast(pthread_cond_t *cond)//唤醒在该cond上等待的所有线程
条件变量的销毁:
int pthread_cond_destroy(pthread_cond_t *cond);
:没有线程在该条件变量上等待时才可销毁该条件变量。
看下面的代码:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<pthread.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //mutex_lock
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //condition variable
typedef struct _Node
{
    int _val;
    struct _Node *_next;
}Node,*pNode,**ppNode;
pNode _head= NULL;
pNode BuyNode(int val)
{
    pNode tmp = (pNode)malloc(sizeof(Node));
    if(tmp)
    {
        tmp->_val = val;
        tmp->_next = NULL;
        return tmp;
    }
    return NULL;
}
void Init_List(ppNode head)
{
    *head = BuyNode(0);
}
//void Init_List()
//{
//  _head = BuyNode(0);
//}
void Push(pNode head,int val)
{
    pNode tmp = BuyNode(val);
    tmp->_next = head->_next;
    head->_next = tmp;
}
int Pop(pNode head)
{
    if(!Is_Empty(head))
    {
        pNode tmp = head->_next;
        int val=tmp->_val;
        head->_next = tmp->_next;
        free(tmp);
        tmp = NULL;
        return val;
    }
    return -1;
}
int Is_Empty(pNode head)
{
    if(head->_next == NULL)
    {
        return 1;
    }
    return 0;
}
void Print_List(pNode head)
{
    pNode tmp = head->_next;
    while(NULL != tmp)
    {
        printf("%d  ",tmp->_val);
        tmp = tmp->_next;
    }
    printf("\n");
}
void* consumer(void* arg)
{
    while(1)
    {
        sleep(1);
        pthread_mutex_lock(&lock);
        while(Is_Empty(_head))
        {
            pthread_cond_wait(&cond,&lock);//生产者等待信号
        }
        int val=Pop(_head);
        printf("consumer: %d\n",val);
        pthread_mutex_unlock(&lock);
    }
    return (void*)0;
}
void* producer(void* arg)
{
    while(1)
    {
        sleep(1);
        pthread_mutex_lock(&lock);
        int val = rand()%10000;
        Push(_head,val);
        printf("producer: %d\n",val);
        pthread_mutex_unlock(&lock);
        pthread_cond_signal(&cond);//生产者生产一个数据并发出信号
    }
    return (void*)0;
}
int main()
{
    Init_List(&_head);//交易场所:链表
    //Init_List();
    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,consumer,NULL);
    pthread_create(&tid2,NULL,producer,NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);//条件变量的销毁
    //Push(_head,1);
    //Push(_head,2);
    //Push(_head,3);
    //Push(_head,4);
    //Push(_head,5);
    //int val=Pop(_head);
    //printf("%d\n",val);
    //Print_List(_head);
    return 0;
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值