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

Yev*_*y P 5 unix multithreading mutex ipc pthreads

我想使用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等函数是否安全?它们是否在不同进程中是线程安全的?

seh*_*ehe 10

从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.
Run Code Online (Sandbox Code Playgroud)

而且来自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.
Run Code Online (Sandbox Code Playgroud)

这里还有一个评论:

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

总而言之,Linux决定在他们的"原生" futex原语之上实现pthread ,它实际上存在于用户进程地址空间中.对于共享同步原语,这将是共享内存,其他进程仍然能够在一个进程终止后查看它.

在流程终止的情况下会发生什么?Ingo Molnar写了一篇名为Robust Futexes的文章.相关报价:

强大的Futexes

但是有一种可能的竞争:由于在glibc获取futex之后添加到列表中以及从列表中删除,因此线程(或进程)有一些指令窗口在那里死亡,而futex挂起.为了防止这种可能性,用户空间(glibc)还维护一个简单的每线程"list_op_pending"字段,以便在获取锁之后线程死亡时允许内核清理,但是在它可以将自己添加到列表之前.Glibc在尝试获取futex之前设置此list_op_pending字段,并在list-add(或list-remove)完成后清除它


摘要

这让你留在其他平台,是开放式的.可以这么说,至少Linux实现已经非常谨慎地满足了我们对鲁棒性的常识期望.

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