pthread_mutex_lock为什么不像往常一样阻塞线程

时间:2016-05-10 03:42:15

标签: c multithreading

最近我读了一些关于线程互斥的代码,相关的代码在这里:

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

  pthread_mutex_t mutex;
  pthread_cond_t cond;
  pthread_t thread;

  void fn(void *arg)
  {
  3     pthread_mutex_lock(&mutex);
        printf( "signal before\n" );
  4     pthread_cond_signal(&cond);
        printf( "signal after\n" );
        pthread_mutex_unlock(&mutex);
  }
  int main()
  {
        int err1;
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond,NULL);

  1     pthread_mutex_lock(&mutex);
  2     err1 = pthread_create(&thread, NULL, fn, NULL);
        usleep(1);
        pthread_cond_wait(&cond,&mutex);
        printf( "main thread get signal\n");
        pthread_mutex_unlock(&mutex);
        pthread_join(thread, NULL);
        pthread_mutex_destroy( &mutex );
        pthread_cond_destroy( &cond );
  }     

在主线程中,首先我调用pthread_mutex_lock函数锁定num 1中的互斥锁,在我在num 2中创建子线程后,在子线程启动函数void fn( void *arg)中调用{{1}再次在num 3中,理论上应该阻塞直到释放互斥锁(主线程),但是为什么它可以继续在子线程中执行num 4中的代码?

执行结果:

result_pic

gcc版本

  

配置: - prefix = / Applications / Xcode.app / Contents / Developer / usr --with-gxx-include-dir = / Applications / Xcode.app / Contents / Developer / Platforms / MacOSX.platform / Developer /SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1   Apple LLVM版本7.3.0(clang-703.0.31)   目标:x86_64-apple-darwin15.4.0   线程模型:posix   InstalledDir:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

非常感谢。

1 个答案:

答案 0 :(得分:1)

条件变量的目的是允许线程等待其他线程中发生的事情。使用互斥锁执行此操作的问题在于以下代码无效:

  1. 获取保护共享状态的锁。
  2. 看看我们是否需要等待,等等。
  3. 糟糕。现在我们在等待锁定时等待。所以没有其他线程可以改变共享状态。所以我们会永远等待。让我们再试一次,这次释放锁:

    1. 获取保护共享状态的锁。
    2. 如果我们需要等待,请释放锁定并等待。
    3. 哎呀,我们还有问题。如果我们等待的东西在我们释放锁定之后但在我们开始等待之前发生了怎么办?再一次,我们将永远等待。

      所以我们需要一个原子&#34;解锁并等待&#34;功能使第2步工作。 pthread_cond_wait是什么。因此,在线程等待时释放互斥锁。

      pthread_cond_wait的规范用法是:

       pthread_mutex_lock(&mutex);
       while (we_need_to_wait)
           pthread_cond_wait(&cond, &mutex);
       // possibly do some stuff while we still hold the mutex
       pthread_mutex_unlock(&mutex);
      

      注意这允许我们决定等待我们仍然持有互斥锁,等待而不保持互斥锁,但是没有窗口可以解除互斥条件,其中互斥锁被释放但我们还没有等待。

      顺便说一句,任何其他方式使用条件变量都非常困难。所以你真的不应该尝试在任何其他模式中使用pthread_cond_wait,直到你对条件变量的工作原理有了深刻的理解。确保您始终确切地知道您正在等待的内容以及您等待的内容受到传递给pthread_cond_wait的互斥锁的保护。