zoukankan      html  css  js  c++  java
  • POSIX 条件变量详细解析

    条件锁pthread_cond_t

    说明,
    等待线程
    1。使用pthread_cond_wait前要先加锁
    2。pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
    3。pthread_cond_wait被激活后会再自动加锁

    激活线程:
    1。加锁(和等待线程用同一个锁)
    2。pthread_cond_signal发送信号
    3。解锁
    激活线程的上面三个操作在运行时间上都在等待线程的pthread_cond_wait函数内部。

    程序示例:

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    pthread_mutex_t count_lock;
    pthread_cond_t count_nonzero;
    unsigned count = 0;
    
    void *decrement_count(void *arg)
    {
        pthread_mutex_lock(&count_lock);
        printf("decrement_count get count_lock\n");
        while(count == 0)
        {
            printf("decrement_count count == 0 \n");
            printf("decrement_count before cond_wait \n");
            pthread_cond_wait(&count_nonzero, &count_lock);
            printf("decrement_count after cond_wait \n");
            printf("decrement_count count = %d \n",count);
        }
    
        count = count + 1;
        pthread_mutex_unlock(&count_lock);
    }
    
    void *increment_count(void *arg)
    {
        pthread_mutex_lock(&count_lock);
        printf("increment_count get count_lock \n");
        if(count == 0)
        {
            printf("increment_count before cond_signal \n");
            pthread_cond_signal(&count_nonzero);
            printf("increment_count after cond_signal \n");
        }
    
        count = count + 1;
        printf("huangcheng \n");
        printf("increment_count count = %d \n",count);
        pthread_mutex_unlock(&count_lock);
    }
    
    int main(void)
    {
        pthread_t tid1, tid2;
    
        pthread_mutex_init(&count_lock, NULL);
        pthread_cond_init(&count_nonzero, NULL);
    
        pthread_create(&tid1, NULL, decrement_count, NULL);
        sleep(2);
        pthread_create(&tid2, NULL, increment_count, NULL);
    
        sleep(10);
        pthread_exit(0);
    
        return 0;
    }
    


    运行结果:

    # gcc -o pthread_cond pthread_cond.c -lpthread
    #./pthread_cond

    decrement_count get count_lock
    decrement_count count == 0
    decrement_count before cond_wait
    increment_count get count_lock
    increment_count before cond_signal
    increment_count after cond_signal
    huangcheng
    increment_count count = 1
    decrement_count after cond_wait
    decrement_count count = 1

    多线程编程,条件变量pthread_cond_t应用

    程序代码:

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    pthread_mutex_t counter_lock;
    pthread_cond_t counter_nonzero;
    int counter = 0;
    int estatus = -1;
    
    void *decrement_counter(void *argv);
    void *increment_counter(void *argv);
    
    int main(int argc, char **argv)
    {
        printf("counter: %d/n", counter);
        pthread_t thd1, thd2;
        int ret;
    
        ret = pthread_create(&thd1, NULL, decrement_counter, NULL);
        if(ret){
            perror("del:/n");
            return 1;
        }
    
        ret = pthread_create(&thd2, NULL, increment_counter, NULL);
        if(ret){
            perror("inc: /n");
            return 1;
        }
    
        int counter = 0;
        while(counter != 10){
            printf("counter: %d/n", counter);
            sleep(1);
            counter++;
        }
    
        return 0;
    }
    
    void *decrement_counter(void *argv)
    {
        pthread_mutex_lock(&counter_lock);
        while(counter == 0)
            pthread_cond_wait(&counter_nonzero, &counter_lock);
    
        counter--;
        pthread_mutex_unlock(&counter_lock);
    
        return &estatus;
    }
    
    void *increment_counter(void *argv)
    {
        pthread_mutex_lock(&counter_lock);
        if(counter == 0)
            pthread_cond_signal(&counter_nonzero);
    
        counter++;
        pthread_mutex_unlock(&counter_lock);
    
        return &estatus;
    }

    运行结果:
    #gcc -o pthread_cond2 pthread_cond2.c -lpthread
    #./pthread_cond2                              
    counter: 0
    counter: 0
    counter: 1
    counter: 2
    counter: 3
    counter: 4
    counter: 5
    counter: 6
    counter: 7
    counter: 8
    counter: 9

    调试程序的运行过程:

    1、开始时 counter 为0 (main)
    2、ret = pthread_create(&thrd1, NULL, decrement_counter, NULL)处生成一个thrd1线程运行decrement_counter(),
    此线程内函数运行流程为:
    先锁定 互斥锁(count_lock) 如果counter为0,此线程被阻塞在条件变量(count_nonzero)上.同时释放互斥锁count_lock(wait内部会先释放锁,等待signal激活后自动再加上锁).
    3、与此同时主程序还在运行,创建另一个线程thrd2运行 increment_counter,
    此线程内的函数流程如下:
    先锁定 互斥锁(count_lock)【wait内部释放锁的互斥锁】 如果counter为0, 唤醒在条件变量(count_nonzero)上的线程即thrd1.但是由于有互斥锁count_lock【signal激活后,wait内部又自动加上锁了】, thrd1还是在等待. 然后count++,释放互斥锁,.......thrd1由于互斥锁释放,重新判断counter是不是为0,如果为0再把线程阻塞在条件变量count_nonzero上,但这时counter已经为1了.所以线程继续运行.counter--释放互斥锁......(退出后,运行主线程main
    4、与此主程序间隔打印counter运行一段时间退出.

     注:更清晰的运行流程请详见如下“改进代码”

    后记,在编译的时候加上 -lpthread
    改进代码:


     

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    pthread_mutex_t counter_lock;
    pthread_cond_t counter_nonzero;
    int counter = 0;
    int estatus = -1;
    
    void *decrement_counter(void *argv);
    void *increment_counter(void *argv);
    
    int main(int argc, char **argv)
    {
        printf("counter: %d/n", counter);
        pthread_t thd1, thd2;
        int ret;
    
        ret = pthread_create(&thd1, NULL, decrement_counter, NULL);
        if(ret){
            perror("del:/n");
            return 1;
        }
    
        ret = pthread_create(&thd2, NULL, increment_counter, NULL);
        if(ret){
            perror("inc: /n");
            return 1;
        }
    
        int counter = 0;
        while(counter != 10){
            printf("counter(main): %d/n", counter);
            sleep(1);
            counter++;
        }
    
        return 0;
    }
    
    void *decrement_counter(void *argv)
    {
        printf("counter(decrement): %d/n", counter);
        pthread_mutex_lock(&counter_lock);
        while(counter == 0)
            pthread_cond_wait(&counter_nonzero, &counter_lock); //进入阻塞(wait),等待激活(signal)
        
        printf("counter--(before): %d/n", counter);    
        counter--; //等待signal激活后再执行
        printf("counter--(after): %d/n", counter);    
        pthread_mutex_unlock(&counter_lock); 
    
        return &estatus;
    }
    
    void *increment_counter(void *argv)
    {
        printf("counter(increment): %d/n", counter);
        pthread_mutex_lock(&counter_lock);
        if(counter == 0)
            pthread_cond_signal(&counter_nonzero); //激活(signal)阻塞(wait)的线程(先执行完signal线程,然后再执行wait线程)
    
        printf("counter++(before): %d/n", counter);    
        counter++; 
        printf("counter++(after): %d/n", counter);    
        pthread_mutex_unlock(&counter_lock);
    
        return &estatus;
    }


     

    运行结果:
    # gcc -o pthread_cond2 pthread_cond2.c -lpthread
    #./pthread_cond2                              
    counter: 0
    counter(main): 0
    counter(decrement): 0
    counter(increment): 0
    counter++(before): 0
    counter++(after): 1
    counter--(before): 1
    counter--(after): 0
    counter(main): 1
    counter(main): 2
    counter(main): 3
    counter(main): 4
    counter(main): 5
    counter(main): 6
    counter(main): 7
    counter(main): 8
    counter(main): 9
  • 相关阅读:
    生成不带签名(BOM)的UTF8格式的XML
    矢量数据的裁剪及合并
    使用dotNET_Reactor4.7加密后的dll在VS2010中无法打包
    加密后的程序在Win8中无法运行
    修改jpg的图片大小
    shapefile中dbf的数据格式(转载)
    shapefile 输出的地理处理注意事项(转载)
    linxu下面的绝对路径和相对路径
    go中的类型转换成interface之后如何复原
    使用docker部署一个go应用
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332860.html
Copyright © 2011-2022 走看看