码迷,mamicode.com
首页 > 编程语言 > 详细

Linux Posix线程条件变量

时间:2017-01-01 18:57:26      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:条件锁   推出   唤醒   rgs   pre   com   lock   efi   img   

技术分享

生产者消费者模型
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进入临界区!\n", tnum);
        //因为就算消费者被唤醒,也需要重新检查g_num的值,因为pthread_cond_wait()函数丢锁之后,可能被其他消费者获得
        //导致多个消费者线程都执行了pthread_cond_wait()函数陷入等待,
        //因为多个消费者线程被pthread_cond_signal()唤醒,但是资源只有一个,可能已经被其他消费者使用了
        //pthread_cond_wait()也有可能被其他信号唤醒
        //所以需要重新判断,而不能使用if
        while (g_num == 0)
        {
            printf("消费者%d开始等待!\n", tnum);
            //在该线程锁上,进行条件等待
            pthread_cond_wait(&cond, &mutex);
            printf("消费者%d被唤醒!\n", tnum);
        }
        //表示已经有资源了,可以消费了
        printf("消费者%d开始消费!\n", tnum);
        g_num--;
        //解锁
        pthread_mutex_unlock(&mutex);
        sleep(3);
    }
    return NULL;
}

//生产者线程
void *product_run(void * arg)
{
    int tnum = (int) arg;
    while (1)
    {
        //当生产者大于消费者时,可能出现生产过多的商品,需要对商品的上限做一个限制,如果商品过多,需要让生产者睡眠
        //涉及到对全局变量的访问,需要加锁
        printf("现有资源个数%d!\n",g_num);
        pthread_mutex_lock(&mutex);
        if (g_num > 20)
        {
            printf("生产者%d产品已经到达上限,进入睡眠!\n", tnum);
            //如果生产产品大于上限,需要睡眠,但是睡眠前应该将锁释放.,留给消费者进行消费
            pthread_mutex_unlock(&mutex);
            sleep(3);
            continue;
        } else
        {
            printf("生产者%d生产产品!\n", tnum);
            //如果生产产品小于上限,那么不需要生产者睡眠,接着生产产品
            g_num++;
            //发送条件信号
            printf("生产者%d发送条件信号!\n", 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 !\n");
            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 !\n");
            return -1;
        }
    }
    //join
    for (i = 0; i < Consume_Count + Product_Count; i++)
    {
        if (pthread_join(thrs[i], NULL) != 0)
        {
            printf("pthread_join() failed !\n");
            break;
        }
    }
    printf("进程推出了!\n");
    return 0;
}

 

Linux Posix线程条件变量

标签:条件锁   推出   唤醒   rgs   pre   com   lock   efi   img   

原文地址:http://www.cnblogs.com/zhanggaofeng/p/6241287.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!