美文网首页程序员
条件变量中使用互斥锁的必要性

条件变量中使用互斥锁的必要性

作者: bazinga_dmc | 来源:发表于2020-05-17 22:04 被阅读0次

    简单介绍一下使用条件变量时,增加互斥锁的必要性。pthread_cond_wait的API如下

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

    条件变量的用法就不具体介绍了,此处我们考虑的问题是增加mutex参数的必要性,先看看课本中的使用方法(只贴了主要的部分,包含生产者和消费者线程):

    #include <stdio.h>
    #include <pthread.h>
    #define MAX 1000000000
    pthread_mutex_t the_mutex;/*互斥锁*/
    pthread_cond_t condc, condp;/*消费者和生产者条件变量*/
    int buffer = 0;
    
    void *producer(void *ptr)
    {
      int i;
      
      for(i = 1; i <= MAX; i++)
      {
        pthread_mutex_lock(&the_mutex);
        while(buffer != 0)/*1*/
        {
          pthread_cond_wait(&condp, &the_mutex);/*2*/
        }
        buffer = i;
        pthread_cond_signal(&condc);
        pthread_mutex_unlock(&the_mutex);
      }
      pthread_exit(0);
    }
    
    void *consumer(void *ptr)
    {
      int i;
      
      for(i = 1; i <= MAX; i++)
      {
        pthread_mutex_lock(&the_mutex);
        while(buffer == 0)/*3*/
        {
          pthread_cond_wait(&condc, &the_mutex);/*4*/
        }
        buffer = 0;
        pthread_cond_signal(&condp);
        pthread_mutex_unlock(&the_mutex);
      }
      pthread_exit(0);
    }
    

    线程在调用pthread_cond_wait并导致阻塞时会解锁互斥锁,解除阻塞并离开pthread_cond_wait时会加锁互斥锁。从代码中可以看到,该特性可以保证语句<1>和语句<3>中对buffer的访问和之后调用pthread_cond_wait导致的阻塞操作的原子性。

    上面的解释可能不够直观,我们考虑一种错误的用法(去掉互斥锁),代码如下:

    void *producer(void *ptr)
    {
      int i;
      
      for(i = 1; i <= MAX; i++)
      {
        while(buffer != 0)/*1*/
        {
          pthread_cond_wait(&condp, NULL);/*2*/
        }
        buffer = i;
        pthread_cond_signal(&condc);
      }
      pthread_exit(0);
    }
    
    void *consumer(void *ptr)
    {
      int i;
      
      for(i = 1; i <= MAX; i++)
      {
        while(buffer == 0)/*3*/
        {
          pthread_cond_wait(&condc, NULL);/*4*/
        }
        buffer = 0;
        pthread_cond_signal(&condp);
      }
      pthread_exit(0);
    }
    

    我们考虑一种可能的线程运行时序,如下所示(buffer初始值为0):

    从图中可以看到在consumer线程对buffer进行访问并准备阻塞的时候,切换至producer线程运行,该线程更改了buffer的值,最终导致两个线程均被阻塞,发生死锁。

    由此可以看出,在使用条件变量时,对需要判断的条件添加互斥锁的必要性。

    相关文章

      网友评论

        本文标题:条件变量中使用互斥锁的必要性

        本文链接:https://www.haomeiwen.com/subject/ceyeohtx.html