pthread_mutex_t & pthread_cond_t 总结( 四 )


3.3 如何使用条件变量我们对「2.3」中的函数 func2 做个简单的修改:
#define MAX 3void *func2(void *arg){    pthread_mutex_lock(&mutex);    puts("线程 th2 抢到锁,开始执行 giNum *= 2");    int i;    for (i = 1; i <= MAX; i++)    {        giNum *= 2;    }    pthread_mutex_unlock(&mutex);    return NULL;}对 func2() 做了个微小的改动:将giNum++修改为了giNum *= 2 。
这样的话,线程抢到锁的顺序不同会影响giNum的最终结果:

  1. th1 先抢到锁:giNum 先执行加操作,然后在执行乘操作,最终结果为 24
  2. th2 先抢到锁:giNum 先执行乘操作,然后在执行加操作,最终结果为 3

pthread_mutex_t &amp; pthread_cond_t 总结

文章插图
如果如何才能做到线程 th1 总是能够先抢到锁呢?下面我们通过条件变量的方式来实现这一想法 。
#include <stdio.h>#include <pthread.h>#include <unistd.h>#define MAX 3#define TRUE 1#define FALSE 0int giNum = 0;int giFlag = FALSE; // TRUE:执行线程 2 的乘操作pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 静态初始化锁pthread_cond_t cond = PTHREAD_COND_INITIALIZER;     // 静态初始化条件变量void *func1(void *arg){    pthread_mutex_lock(&mutex);    puts("线程 th1 抢到锁");    puts("线程 th1 开始执行 giNum++");    int i;    for (i = 1; i <= MAX; i++)    {        giNum++;    }    giFlag = TRUE; // 修改 giFlag 的值,使得线程 th2 满足条件    pthread_cond_signal(&cond); // 向线程 th2 发出信号    pthread_mutex_unlock(&mutex);    return NULL;}void *func2(void *arg){    pthread_mutex_lock(&mutex);    puts("线程 th2 抢到锁");    while (FALSE == giFlag) // 不满足线程 th2 的执行条件    {        puts("线程 th2 不满足条件,等待~");        pthread_cond_wait(&cond, &mutex); // 等待被触发    }    puts("线程 th2 满足条件,开始执行 giNum *= 2");    int i;    for (i = 1; i <= MAX; i++)    {        giNum *= 2;    }    pthread_mutex_unlock(&mutex);    return NULL;}int main(){    pthread_t th1;    pthread_create(&th1, NULL, func1, NULL);    pthread_t th2;    pthread_create(&th2, NULL, func2, NULL);    pthread_join(th1, NULL);    pthread_join(th2, NULL);    printf("giNum = %d\n", giNum);    return 0;}

经验总结扩展阅读