pthread强大的互斥锁有多安全?

时间:2013-10-15 08:04:29

标签: multithreading unix pthreads ipc mutex

我正在考虑使用Posix强大的互斥锁来保护不同进程之间的共享资源(在Linux上)。然而,在不同情况下对安全性存在一些疑问。我有以下问题:

  1. 是否在内核或用户代码中实现了强大的互斥锁?

  2. 如果是后者,如果在调用pthread_mutex_lock或pthread_mutex_unlock并且共享pthread_mutex数据结构更新时进程发生崩溃会发生什么?

    我理解如果一个进程锁定互斥锁并且死掉,另一个进程中的线程将被唤醒并返回EOWNERDEAD。但是,如果正在更新pthread_mutex数据结构(在共享内存中)时,如果进程死亡(在不太可能的情况下)会发生什么?在这种情况下,互斥锁会被破坏吗?如果要调用pthread_mutex函数,映射到同一共享内存的另一个进程会发生什么? 在这种情况下,互斥锁是否仍然可以恢复?

  3. 此问题适用于具有PTHREAD_PROCESS_SHARED属性的任何pthread对象。在同一个来自不同进程的对象上同时调用pthread_mutex_lock,pthread_mutex_unlock,pthread_cond_signal等函数是否安全?它们是否在不同进程中是线程安全的?

2 个答案:

答案 0 :(得分:9)

来自pthreads的手册页:

 Over time, two threading implementations have been provided by the
   GNU C library on Linux:

   LinuxThreads
          This is the original Pthreads implementation.  Since glibc
          2.4, this implementation is no longer supported.

   NPTL (Native POSIX Threads Library)
          This is the modern Pthreads implementation.  By comparison
          with LinuxThreads, NPTL provides closer conformance to the
          requirements of the POSIX.1 specification and better
          performance when creating large numbers of threads.  NPTL is
          available since glibc 2.3.2, and requires features that are
          present in the Linux 2.6 kernel.

   Both of these are so-called 1:1 implementations, meaning that each
   thread maps to a kernel scheduling entity.  Both threading
   implementations employ the Linux clone(2) system call.  In NPTL,
   thread synchronization primitives (mutexes, thread joining, and so
   on) are implemented using the Linux futex(2) system call.

来自man futex(7):

   In its bare form, a futex is an aligned integer which is touched only
   by atomic assembler instructions.  Processes can share this integer
   using mmap(2), via shared memory segments or because they share
   memory space, in which case the application is commonly called
   multithreaded.

发现了另一条评论here

  

(如果您想知道它们如何在共享内存中工作: Futexes以其物理地址为基础

总结一下,Linux决定在他们的“原生”futex原语之上实现pthread,它实际上存在于用户进程地址空间中。对于共享同步原语,这将是共享内存,并且在一个进程终止后,其他进程仍然可以看到它。

流程终止时会发生什么? Ingo Molnar写了一篇名为Robust Futexes的文章。相关引用:

  

健壮的Futexes

     

虽然有一场比赛可能:因为加入和删除   列表是在glibc获得futex后完成的,有几个   线程(或进程)死亡的指令窗口   futex挂了。为了防止这种可能性,用户空间(glibc)   还维护一个简单的每线程'list_op_pending'字段,以允许   如果线程在获取锁定后死亡,则清理内核,但只是   之前它可以将自己添加到列表中。 Glibc设定了这个   list_op_pending字段在尝试获取futex之前,并清除   在list-add(或list-remove)完成后


摘要

这使您无法使用其他平台,这是开放式的。我只想说Linux实现至少已经非常谨慎地满足了我们对鲁棒性的常识期望。

看到其他操作系统通常首先采用基于内核的同步原语,我认为它们的实现更自然可靠。

答案 1 :(得分:0)

根据http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_getrobust.html的文档,它确实读到在完全兼容POSIX的操作系统中,带有稳健标志的共享互斥将以您期望的方式运行。

问题显然是,并非所有操作系统都完全兼容POSIX。甚至那些自称不是的人。进程共享的互斥锁,特别是健壮的互斥锁,通常不在操作系统的POSIX实现的一部分。