当一个线程在等待互斥锁时死亡会发生什么



如果一个进程有三个线程,T1, T2和T3,并且这三个线程都试图获取互斥锁M1上的锁,我理解其中一个将获取互斥锁,而另外两个将等待,直到它们获得互斥锁。

如果我使用pthread_mutexattr_setrobust()使线程健壮,那么我理解如果T1持有M1,并且T1在释放之前终止,M1, T2被EOWNERDEAD的返回值唤醒。T2可以清理被保护资源的状态。

现在,如果T1拥有M1,而T2和T3都在等待M1,会发生什么?T2终止。会发生什么呢?当T1释放M1时,互斥体会直接进入T3吗?T3是否得到EOWNERDEAD,或者它只是看起来像什么都没有发生,不需要清理?看起来T3应该取M1因为T2不能让线程进入不一致的状态。答案吗?这对我来说是一个智力上的问题,而不是试图解决一个特定的问题,所以我很感激你能指点我进一步阅读这个主题。

编辑:我不是试图弄清楚如何做正确的,相反,我试图弄清楚发生了什么,一般对于pthread实现,当T2被终止或被取消(对这两种情况都感兴趣,只是开始理解它可能对结果产生的差异)。它是定义行为吗?

我的目标平台是Windows,使用Windows服务的Unix,以防它是平台相关的,但我的兴趣是一般应该发生什么。https://technet.microsoft.com/en-us/library/bb463209.aspx.

注意:我的回答完全基于书面标准,而不是基于个人经验或相关专业知识。

取消pthread分为两种情况:

如果pthread被配置为延迟取消(这是默认值),那么根据标准的字面读数,取消请求将不会被处理,直到互斥锁被请求(或未被请求)之后,因为pthread_mutex_lock和friends不在标准2.9.5节所示的可取消函数列表中。

我不确定各种实现是否实际上是这样的,因为它似乎不受欢迎。如果一个实现实际上允许在尝试声明互斥锁时取消(可能是因为pthread_mutex_lock函数内部使用了列出的可取消函数之一),我希望它会导致互斥锁保持一致,并且按照Jille的回答未被声明,但标准似乎没有明确要求。

如果pthread被配置为异步取消,行为是未定义的:

pthread_cancel()、pthread_setcancelstate()和pthread_setcanceltype()函数被定义为async-cancel安全的。

本POSIX.1-2008卷中的其他函数不需要是异步取消安全的。

如果一个线程启用了异步取消,并且在执行非异步取消安全的函数时被取消,则该行为是未定义的。

似乎不可能终止单个pthread。来自第2.4.3节:

当一个信号被传递给一个线程时,如果该信号的动作指定终止、停止或继续,则整个进程应分别被终止、停止或继续。

您必须使用条件变量才能使其完美工作。我复制粘贴了一些文档下面。

条件变量允许线程同步到共享资源的值。通常,条件变量用作线程之间的通知系统。

例如,你可以有一个计数器,一旦达到一定的计数,你希望线程被激活。一旦计数器达到限制,激活的线程(或多个线程)将等待条件变量。活动线程在这个条件变量上发出信号,通知其他等待/睡眠在这个条件变量上的线程;从而导致一个等待线程被唤醒。如果您想通知等待条件变量唤醒的所有线程,也可以使用广播机制。从概念上讲,这是由右图中的伪代码建模的。

当等待条件变量时,等待应该在循环中,而不是在简单的if语句中,因为会出现错误的唤醒。你不能保证如果一个线程被唤醒,它是一个信号或广播调用的结果。

文档链接:http://randu.org/tutorials/threads/

根据POSIX.1-2008tc1的pthread_mutex_lock()规范:

  • 如果pthread_mutex_lock()返回0或[EOWNERDEAD],线程将成为互斥锁的所有者。
  • [EOWNERDEAD]错误发生在包含拥有线程(或可选的,拥有线程)的进程在拥有互斥锁时终止时。

在您的示例中,pthread_mutex_lock()没有成功获取T2,因此T3将毫无错误地获取M1。

相关内容

最新更新