您的位置:首页 > 其它

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

2014-07-31 16:45 417 查看
理解条件变量的一个例子
看条件变量的时候将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 里面再加几条语句,会发现结果更坑的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: