互斥锁和pthread_join的区别

6

这两者有什么区别?

它们不是同一件事吗?它们都等待一个线程完成后才执行另一个线程,对吧?

我正在尝试理解以下代码。

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

void *functionC();
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int  counter = 0;

main()
{
    int rc1, rc2;
    pthread_t thread1, thread2;

 /*Create independent threads each of which will execute functionC */

     if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) )
   {
      printf("Thread creation failed: %d\n", rc1);
   }

   if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) )
   {
      printf("Thread creation failed: %d\n", rc2);
   }

   /* Wait till threads are complete before main continues. Unless we  */
   /* wait we run the risk of executing an exit which will terminate   */
   /* the process and all threads before the threads have completed.   */

   pthread_join( thread1, NULL);
   pthread_join( thread2, NULL);

   exit(0);
}    
void *functionC()
{
   pthread_mutex_lock( &mutex1 );
   counter++;
   printf("Counter value: %d\n",counter);
   pthread_mutex_unlock( &mutex1 );
}

感谢您的选择。

5
它们并不特别相似。这有点像问一个苹果和供给侧经济学之间的区别是什么。 - tylerl
2个回答

11

它们实际上并不是同一个东西。

互斥锁(mutex,互斥信号量)是一种限制资源在同一时间只能被一个线程使用的手段(假定两个线程都能运行)。当线程从 pthread_mutex_lock 调用中成功返回时,它保证是唯一持有该锁的线程。任何尝试在此之后锁定该互斥锁的线程通常都必须等到拥有锁的线程解锁为止。

换句话说,拥有锁的线程是唯一能够操作由该锁保护的资源的线程(当然,假设其他线程在首先获取锁之前不会触及该资源 - 你必须遵守规则)。

另一方面,pthread_join 允许一个线程等待另一个线程退出。这通常在主线程中使用,以等待所有子线程退出(还有其他用途,那只是典型的一个)。从 pthread_join 成功返回意味着另一个线程不再运行。

在您提供的代码中,两个线程同时运行,并且 counter 增量和 printf 调用都受 mutex1 保护。在 main 结束时的 pthread_join 调用将使主线程等待您的两个子线程退出后才继续执行。

顺便说一下,您应该检查从 pthread_mutex_lock 返回的值,因为它可能会失败。在这种情况下,您不要继续修改受保护的资源,因为可能会导致损坏。对于 pthread_join 也是如此。

而且,为了进行更全面的测试,以下函数会更好:

void *functionC() {
    int i;
    for (i = 1000; i > 0; i--) {
        pthread_mutex_lock (&mutex1);
        counter++;
        printf ("Counter value: %d\n", counter);
        pthread_mutex_unlock (&mutex1);
    }
}

因为这样更有可能让线程并行运行。如果没有循环,第一个线程退出之前第二个线程甚至还没开始的情况很常见。


你所说的“资源”,是指线程正在使用的变量吗? - John
1
@Ted,这只是一个例子。但是互斥锁可以用于保护变量,防止代码在两个线程同时运行,阻止来自多个线程的终端输出混合以及许多其他事情。 - paxdiablo
除非实现为 pthread_mutex_lock 定义了额外的错误条件,或者您正在使用特殊的互斥类型(如错误检查或鲁棒性),否则 pthread_mutex_lock 不会失败。如果它在实现特定的错误上失败了,我不确定您该如何处理。我认为,除非使用鲁棒互斥锁,否则不检查返回值是非常合理的。 - R.. GitHub STOP HELPING ICE

3

pthread_join() 等待线程退出。 mutex_lock 获取一个信号量,防止协作线程同时访问受保护的资源。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接