linux知识(二)互斥量、信号量和生产者消费者模型

linux知识(二)互斥量、信号量和生产者消费者模型

一、互斥量

产生原因

使用多线程常常会碰到数据混乱的问题,那么使用互斥量,相当于“加锁”的操作,将有助于解决数据混乱的问题
每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁
资源还是共享的,线程间也还是竞争的,
但通过“锁”就将资源的访问变成互斥操作,而后与时间有关的错误也不会再产生了。

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

pthread_mutex_t mutex;  //定义锁
void* tfn(void* arg)
{
    srand(time(NULL));

    while (1) {
  
        pthread_mutex_lock(&mutex);
        printf("hello ");
        sleep(rand() % 3);	/*模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误*/
        printf("world\n");
        pthread_mutex_lock(&mutex);
        
        pthread_mutex_unlock(&mutex);
        sleep(rand() % 3);
    }

    return NULL;
}

int main(void)
{
    int flg = 5;
    pthread_t tid;
    srand(time(NULL));
    pthread_mutex_init(&mutex,NULL); //mutex==1,初始化锁
    pthread_create(&tid,NULL,tfn,NULL);
    while (1) {
        pthread_mutex_lock(&mutex);
        printf("HELLO ");
        sleep(rand() % 3);
        printf("WORLD\n");
        pthread_mutex_unlock(&mutex);
        sleep(rand() % 3);
       
    }
    pthread_cancel(tid);
    pthread_join(tid, NULL);

    pthread_mutex_destroy(&mutex);

    return 0;
}

二、信号量

互斥量的操作是1对1的,一个线程加锁与解锁完成后,下一个线程通过竞争在拿到锁进行操作,对于多线程并发来说,无形间效率就变低了。多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。线程从并行执行,变成了串行执行。与直接使用单进程无异。信号量能有效的解决这一问题。

生产者消费者模型

说到信号量,就必须提到生产者消费者模型
在这里插入图片描述
我们来假设一下这样一个情景,图中有生产者,消费者以及有5个盘子。生产者只有生产了,消费者才能拿到东西。我们定义5个线程来当作生产者持续生产,它们需要拿到盘子来生产,它们不在像用拿“锁”的方式一个一个来生产,这样无形之中就提高了效率,提高了并发型。消费等生产者生产完,通过竞争来抢这些消费品。

#include <cstdio>
#include <pthread.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>

using namespace std;
int g_count=0;
pthread_mutex_t prod_mutex;
pthread_mutex_t cur_mutex;
sem_t g_sem_prod;//生产者信号量
sem_t g_sem_cur; //消费者的信号量



void * add(void *arg)
{
    //生产者
    cout << " thread .. wait .. id = " << pthread_self() << endl;
    //开启保护线程
    sem_wait(&g_sem_prod);
    pthread_mutex_lock(&prod_mutex);
    g_count++;
    printf("make cake ... g_count = %d\n",g_count);
    //解除保护
    pthread_mutex_unlock(&prod_mutex);
    sem_post(&g_sem_cur);
    sleep(rand() % 3);

}

void* sub(void* arg)
{
    //消费者
    cout << "wait cake  thread .. wait .. id = " << pthread_self() << endl;
    sem_wait(&g_sem_cur);
    //开启保护线程
    pthread_mutex_lock(&cur_mutex);
    g_count--;
    printf("eat.......g_count = %d\n", g_count);
    //解除保护
    pthread_mutex_unlock(&cur_mutex);
    sem_post(&g_sem_prod);
    sleep(rand() % 3);

}


int main()
{
    int i = 0;
    pthread_t tid;
    int ret;
    pthread_mutex_init(&prod_mutex,NULL);
    pthread_mutex_init(&cur_mutex, NULL);

    sem_init(&g_sem_prod,0,5);
    sem_init(&g_sem_cur,0, 0);
    //线程 加一操作
    for (i = 0; i < 5; i++)
    {
        ret = pthread_create(&tid, NULL, add, NULL);
        if (ret != 0)
        {
            cout << strerror(ret) << endl;
            return 0;
        }
    }
    //消费者
    for (i = 0; i < 5; i++)
    {
        ret=pthread_create(&tid, NULL, sub, NULL);
        if (ret != 0)
        {
            cout << strerror(ret) << endl;
            return 0;
        }

    }



    while (1)
    {

    }
    
    
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chenshida_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值