理解条件变量使用的一个例子

本文通过两个实例解析了条件变量的工作原理及应用。首先介绍了条件变量在Linux C编程中的基本使用,并针对一个存在死循环问题的程序进行了分析。随后,通过一个改进的示例程序详细解释了条件变量如何协调两个线程交替输出奇偶数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理解条件变量的一个例子

       看条件变量的时候将linux C 编程的例8-5代码抄了一遍,如下:

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

pthread_mutex_t   mutex;
pthread_cond_t    cond;

void * thread1(void *arg)
{
    pthread_cleanup_push(pthread_mutex_unlock,&mutex);

    while(1)
    {
        printf("thread1 is running\n");
        pthread_mutex_lock (&mutex);
        pthread_cond_wait (&cond,&mutex);
        printf("thread1 applied the condition\n");
        pthread_mutex_unlock (&mutex);
        sleep(1);
    }

    pthread_cleanup_pop(0);
}

void * thread2(void *arg)
{
    while(1)
    {
        printf("thread2 is running\n");
        pthread_mutex_lock(&mutex);
        pthread_cond_wait (&cond,&mutex);
        printf("thread2 applied the condition\n");
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main(void)
{
    int num=0;
    pthread_t tid1,tid2;

    printf("condition variable study!\n");
    pthread_mutex_init (&mutex,NULL);
    pthread_cond_init (&cond,NULL);
    pthread_create(&tid1,NULL,(void *)thread1,NULL);
    pthread_create(&tid2,NULL,(void *)thread2,NULL);

    do
    {
        pthread_cond_signal(&cond);     //给等待的线程发信号
    }while(1);

    sleep(50);
    pthread_exit(0);
}


       然后将执行结果重定义到一个 .txt 文档里,几分钟后回头一看,呆了,这程序居然还在运行。显然这就是一个死循环,之后就开始找哪出了问题。

       有点坑啊!看了半天没看懂条件变量在这里有什么作用,自然根据这个程序就没理解了条件变量这一块内容。


        还是去问问度娘吧。看了好几个关于条件变量介绍的网页,总算理解的差不多了。

下面是测试自己想法的时候根据书上那个例子改的程序,感觉比书上那个好理解:

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

pthread_mutex_t   mutex;
pthread_cond_t    cond;
int               flag=0;           

void * thread1(void *arg)
{
    pthread_cleanup_push(pthread_mutex_unlock,&mutex);

    for(flag=0;flag<=10;flag++)
    {
        printf("thread1 is running\n");
        pthread_mutex_lock (&mutex);
        if(flag%2==0)
          pthread_cond_signal(&cond);//阻塞,通知正在等待此条件为真的线程
        else
          printf("flag of thread1  = %d\n",flag);
        pthread_mutex_unlock (&mutex);
        sleep(1);
    }

    pthread_cleanup_pop(0);
}

void * thread2(void *arg)
{
    while(flag<10)
    {
        printf("thread2 is running\n");
        pthread_mutex_lock(&mutex);
        if(flag%2!=0)
        {
            pthread_cond_wait (&cond,&mutex);//等待glag%2==0的信号
        }
        printf("flag of thread2  = %d\n",flag);
        
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main(void)
{
    int num=0;
    pthread_t tid1,tid2;

    printf("condition variable study!\n");
    pthread_mutex_init (&mutex,NULL);  //初始化互斥锁
    pthread_cond_init (&cond,NULL);    //初始化条件变量
    pthread_create(&tid1,NULL,(void *)thread1,NULL);//线程tid 1
    pthread_create(&tid2,NULL,(void *)thread2,NULL);//线程tid 2

    sleep(11);
    pthread_mutex_destroy(&mutex);//清除互斥锁
    pthread_cond_destroy(&cond);  //清除条件变量
}

输出结果:

condition variable study!
thread2 is running
thread1 is running
flag of thread2  = 0
thread2 is running
thread1 is running
flag of thread1  = 1
thread1 is running
flag of thread2  = 2
thread1 is running
flag of thread1  = 3
thread2 is running
thread1 is running
flag of thread2  = 4
thread1 is running
flag of thread1  = 5
thread2 is running
thread1 is running
flag of thread2  = 6
thread1 is running
flag of thread1  = 7
thread2 is running
thread1 is running
flag of thread2  = 8
thread1 is running
flag of thread1  = 9
thread2 is running
thread1 is running
flag of thread2  = 10

      从结果可以看出,上面的程序是用来划分0到10内的奇数和偶数的,线程1只输出奇数,线程2只负责输出偶数。

      分析一下代码,看看条件变量扮演了什么角色:

      线程1中,如果flag是偶数,调用pthread_cond_signal(&cond),这个函数会让当前进程阻塞,把条件为真的信号发给正在等待此信号的线程,告诉他“这个flag是偶数,交给你处理了”。如果是奇数,不发信号,输出flag。

       与他对应的接受信号的是线程2,在线程2中,如果遇到flag不是偶数,那么调用

pthread_cond_wait (&cond,&mutex)线程阻塞,等待flag为偶数的信号传来唤醒进程后,才能继续执行剩下的语句。

       说说 pthread_cond_wait ()是怎么工作的,执行这个函数时,他主要相当于做下面几个工作:

      解锁----> 等待 ------>加锁

       pthread_cond_wait 自动解锁互斥量(如同执行了 pthread_mutex_unlock),并等待条件变量触发。这时线程挂起,不占用 CPU 时间,直到条件变量被触发。pthread_cond_wait 函数返回前,自动重新对互斥量加锁(如同执行了 pthread_mutex_lock)。

       使用 pthread_cond_wait ()之前必须使用pthread_mutex_lock()加锁,为什么呢? 这里要保证操作是原子性的,防止条件变量改变,如果不加锁,条件变量很可能被其他线程改变。那wait 函数之后为什么又要解锁,因为pthread_cond_wait ()在返回之前又给重新加了锁,所以函数调用完还要解锁。


      pthread_cond_signal 使在条件变量上等待的线程中的一个线程重新开始。如果没有等待的线程,则什么也不做。如果有多个线程在等待该条件,只有一个能重启动,但不能指定哪一个。


       哦,说下第一个程序为什么那么坑爹的死循环了:

       主要是main函数里面 do { }while(1) 那两句导致的,主线程执行到这一段循环时,条件永真,会无休止的调用 pthread_cond_signal()给两个线程任意一个线程发信号,后面那sleep(50)根本没机会执行。有兴趣的话给do 里面再加几条语句,会发现结果更坑的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值