• Linux Posix线程条件变量


    生产者消费者模型
    1.多个线程操作全局变量n,需要做成临界区(要加锁--线程锁或者信号量)
    2.调用函数pthread_cond_wait(&g_cond,&g_mutex)让这个线程锁在某一个条件上等待
    --pthread_cond_wait()函数的本质是①:拿到锁的线程,把锁暂时丢掉(解锁)②:线程休眠,进行等待③:线程等待通知,醒来继续执行(重新获得锁)
    --这个pthread_cond_wait()函数是一个原子性操作
    --注意:丢掉的锁可以被生产线程获得,也可以被消费线程获得,消费者线程获取会陷入等待,生产者线程获得会发送信号,唤醒消费者
    3.pthread_cond_signal()生产者拿到锁,生产n,生产完成后,发送信号给消费者(唤醒消费者),生产者离开临界区
    //生产者消费者模型
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <pthread.h>
    
    //定义线程锁
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    //定义线程条件锁
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    //定义全局变量
    int g_num = 0;
    
    //定义消费者线程数量
    #define Consume_Count 2
    
    //定义生产者线程数量
    #define Product_Count 4
    
    //消费者线程
    void *consume_run(void * arg)
    {
        int tnum = (int) arg;
        while (1)
        {
            //因为多线程操作一个全局变量,需要做成临界区,枷锁
            pthread_mutex_lock(&mutex);
            printf("消费者%d进入临界区!
    ", tnum);
            //因为就算消费者被唤醒,也需要重新检查g_num的值,因为pthread_cond_wait()函数丢锁之后,可能被其他消费者获得
            //导致多个消费者线程都执行了pthread_cond_wait()函数陷入等待,
            //因为多个消费者线程被pthread_cond_signal()唤醒,但是资源只有一个,可能已经被其他消费者使用了
            //pthread_cond_wait()也有可能被其他信号唤醒
            //所以需要重新判断,而不能使用if
            while (g_num == 0)
            {
                printf("消费者%d开始等待!
    ", tnum);
                //在该线程锁上,进行条件等待
                pthread_cond_wait(&cond, &mutex);
                printf("消费者%d被唤醒!
    ", tnum);
            }
            //表示已经有资源了,可以消费了
            printf("消费者%d开始消费!
    ", tnum);
            g_num--;
            //解锁
            pthread_mutex_unlock(&mutex);
            sleep(3);
        }
        return NULL;
    }
    
    //生产者线程
    void *product_run(void * arg)
    {
        int tnum = (int) arg;
        while (1)
        {
            //当生产者大于消费者时,可能出现生产过多的商品,需要对商品的上限做一个限制,如果商品过多,需要让生产者睡眠
            //涉及到对全局变量的访问,需要加锁
            printf("现有资源个数%d!
    ",g_num);
            pthread_mutex_lock(&mutex);
            if (g_num > 20)
            {
                printf("生产者%d产品已经到达上限,进入睡眠!
    ", tnum);
                //如果生产产品大于上限,需要睡眠,但是睡眠前应该将锁释放.,留给消费者进行消费
                pthread_mutex_unlock(&mutex);
                sleep(3);
                continue;
            } else
            {
                printf("生产者%d生产产品!
    ", tnum);
                //如果生产产品小于上限,那么不需要生产者睡眠,接着生产产品
                g_num++;
                //发送条件信号
                printf("生产者%d发送条件信号!
    ", tnum);
                pthread_cond_signal(&cond);
                pthread_mutex_unlock(&mutex);
            }
            pthread_mutex_unlock(&mutex);
            sleep(2);
        }
        return NULL;
    }
    
    int main(int arg, char * args[])
    {
        pthread_t thrs[Consume_Count + Product_Count];
        int i = 0;
        for (i = 0; i < Consume_Count; i++)
        {
            if (pthread_create(&thrs[i], NULL, consume_run, (void *) i) != 0)
            {
                printf("pthread_create() failed !
    ");
                return -1;
            }
        }
        for (i = 0; i < Product_Count; i++)
        {
            if (pthread_create(&thrs[i + Consume_Count], NULL, product_run,
                    (void *) i) != 0)
            {
                printf("pthread_create() failed !
    ");
                return -1;
            }
        }
        //join
        for (i = 0; i < Consume_Count + Product_Count; i++)
        {
            if (pthread_join(thrs[i], NULL) != 0)
            {
                printf("pthread_join() failed !
    ");
                break;
            }
        }
        printf("进程推出了!
    ");
        return 0;
    }
  • 相关阅读:
    城市生态规划关键技术方法之三:城市生态系统服务功能理论与方法
    AE中用矢量数据剪裁栅格
    城市生态规划的基本原理与程序
    城市生态规划关键技术方法之一:生态系统健康理论与方法
    城市生态规划的基本概念、内容与方法
    终于找到使用Sql Server Management Studio导致蓝屏的罪魁祸首了
    保证相同类型的MDI子窗体只会被打开一次的方法
    甩掉数据字典,让Sql Server数据库也来一个自描述
    新鲜试用IE8 beta2
    让我目瞪口呆的program.exe
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6241287.html
Copyright © 2020-2023  润新知