zoukankan      html  css  js  c++  java
  • linux网络编程-posix条件变量(40)

    举一个列子来说明条件变量:

    假设有两个线程同时访问全局变量n,初始化值是0,

    一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待。

    另外一个线程也是进入临界区,修改n的值,当修改了n的值后,需要向等待中的线程发送通知,修改了n的值。但是现在存在这样的一个问题:当第一个线程进入临界区的时候,第一个线程一直处在等待n改变的状态,第二个线程是无法进入临界区的修改n的值的,这样第一个线程

    就处于死锁了。上面这个问题可以时候条件变量来解决。

    条件变量也可以用于生产者和消费者的状态:

    假设一个线程访问一个队列该队列是空的,那么该线程只能处于阻塞状态,直到其他线程将一个产品添加到队列中,发现通知通知等待的线程

    对于等待条件的代码,首先需要锁定互斥量,因为这个条件变量是多个线程都可以同时访问的,所以需要进行互斥,这里使用while 等待只要条件为假,该线程就一直处于等待状态

    对于给条件发现信号的代码:首先也是需要进行互斥,然后设置条件为真,然后给等待的线程发一个通知

    下面我们使用条件变量来进行生产者与消费者的问题

    int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

    pthread_cond_init函数可以用来初始化一个条件变量。他使用变量attr所指定的属性来初始化一个条件变量,如果参数attr为空,那么它将使用缺省的属性来设置所指定的条件变量。

    pthread_cond_destroy函数可以用来摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不要求等待在参数所指定的条件变量上。

    int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

    cond 条件变量

    mutex 互斥锁

     第一个参数*cond是指向一个条件变量的指针。第二个参数*mutex则是对相关的互斥锁的指针。

    int pthread_cond_signal(pthread_cond_t *cond);

    int pthread_cond_broadcast(pthread_cond_t *cond);

    参数*cond是对类型为pthread_cond_t 的一个条件变量的指针。当调用pthread_cond_signal时一个在相同条件变量上阻塞的线程将被解锁。如果同时有多个线程阻塞,则由调度策略确定接收通知的线程。如果调用pthread_cond_broadcast,则将通知阻塞在这个条件变量上的所有线程。一旦被唤醒,线程仍然会要求互斥锁。如果当前没有线程等待通知,则上面两种调用实际上成为一个空操作。如果参数*cond指向非法地址,则返回值EINVAL。

    #include <unistd.h>
    #include <sys/types.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    
    #define ERR_EXIT(m) 
            do 
            { 
                    perror(m); 
                    exit(EXIT_FAILURE); 
            } while(0)
    
    #define CONSUMERS_COUNT 1
    #define PRODUCERS_COUNT 1
    #define BUFFSIZE 10
    
    //首先定义一个条件变量
    pthread_cond_t g_cond; 
    
    unsigned short in = 0;
    unsigned short out = 0;
    unsigned short produce_id = 0;
    unsigned short consume_id = 0;
    int nReady = 0;//表示当前产生的数目的计数器 
    pthread_mutex_t g_mutex;
    
    pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT];
    
    void *consume(void *arg)
    {
        int i;
        int num = (int)arg;
        while (1)
        {
            // 首先需要进行互斥
            pthread_mutex_lock(&g_mutex);
            while(nReady == 0){//等待产品不为空 
            //条件变量需要和互斥锁进行配合使用 
            printf("consume thread_id %d now is waiting for .....
    ",num); 
                pthread_cond_wait(&g_cond,&g_mutex); 
            }
            printf("consume thread_id %d now is begin consume product 
    ",num); 
            //消费产品,将产品数据减一
             nReady = nReady -1; 
            pthread_mutex_unlock(&g_mutex);
            sleep(1); 
          
        }
        return NULL;
    }
    
    void *produce(void *arg)
    {
        int num = (int)arg;
        int i;
        while (1)
        {
                // 首先需要进行互斥
            pthread_mutex_lock(&g_mutex);
            //开始生产产品
             nReady = nReady +1;
             //发起通知
            printf("producter thread_id %d now is singal for consume .....
    ",num); 
            pthread_cond_signal(&g_cond);
            pthread_mutex_unlock(&g_mutex);
            sleep(3);
        }
        return NULL;
    }
    
    int main(void)
    {
        int i;
        
    
        //初始化一个互斥锁 
        pthread_mutex_init(&g_mutex, NULL);
        //初始化条件变量
        pthread_cond_init(&g_cond,NULL);
         
    
        for (i = 0; i < CONSUMERS_COUNT; i++)
            pthread_create(&g_thread[i], NULL, consume, (void *)i);
    
        for (i = 0; i < PRODUCERS_COUNT; i++)
            pthread_create(&g_thread[CONSUMERS_COUNT + i], NULL, produce, (void *)i);
    
        for (i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++)
            pthread_join(g_thread[i], NULL);
    
        //销毁互斥锁 
        pthread_mutex_destroy(&g_mutex);
        //销毁条件变量
        pthread_cond_destroy(&g_mutex); 
    
        return 0;
    }

    编译下代码:

    gcc product.c -o product -lpthread

    运行代码:

     ./product 

    代码中生产者和消费者都只有一个线程

    我们来看程序运行的结果:

    pthread_cond_wait前要先加锁
         pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
         pthread_cond_wait被激活后会再自动加锁 

    pthread_cond_wait的内部实现流程:

    1、第一步首先对互斥锁进行解锁

    2、第二步等待其他线程改变条件变量

    3、然后自动加锁后退出等待

  • 相关阅读:
    php 图形用户界面GUI 开发
    centos实现两种秒级任务的简单方法
    rsync同步工具的配置与使用
    【转】网络字节序与主机字节序
    【转】Visual Studio 非常实用的调试技巧
    【原/转】【boost】智能指针使用规则以及介绍
    【转】一个非常常见但容易被忽略的c++问题——用IPML模式可以解决
    【转】Visual Studio项目相对路径的设置,实用
    【原】visual studio添加现有文件夹的方法
    【原】自定义UINavigationItem的两种方法以及相应的隐藏方法
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/7115723.html
Copyright © 2011-2022 走看看