当pthread在等待互斥锁时死机会发生什么?

时间:2016-10-11 19:51:05

标签: c windows multithreading

如果一个进程有三个线程,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,就像从未发生任何事情那样,并且不需要清理?似乎T3应该只采用M1,因为T2无法使线程进入不一致状态。任何答案?这是一个让我感兴趣的问题,而不是试图解决一个特定的问题,所以我们将不胜感激。

编辑:我不是想弄清楚如何正确地做,而是我试图弄清楚当T2被终止或被取消时(通常对于pthread实现会发生什么)(对两种情况都感兴趣,并且仅开始了解它可能对结果产生的差异)。它是否定义了行为?

我的目标平台是Windows使用Windows Services for Unix,以防它依赖于平台,但我对应该发生的事情感兴趣。 https://technet.microsoft.com/en-us/library/bb463209.aspx

3 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

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

取消pthread分为两种情况:

如果pthread配置为延迟取消(这是默认值),那么根据标准的字面读数,取消请求直到声明互斥量(或未能声明)之后才会被处理{ {1}}和朋友不在可以取消的功能列表中,如in section 2.9.5 of the standard所示。

我不确定各种实现是否真的以这种方式运行,因为它似乎是不合需要的。如果实现确实允许在尝试声明互斥锁时取消(可能是因为CMD ["sh", "-c", "/opt/jdk/bin/java -jar ${ARTIFACTID}-${VERSION}.${PACKAGING}"] 函数内部使用了列出的可取消函数之一),我希望它会导致互斥锁保持一致并且无人问津,根据Jille的回答,但标准似乎并没有明确要求它。

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

  

pthread_cancel(),pthread_setcancelstate()和pthread_setcanceltype()函数被定义为async-cancel safe。

     

本卷POSIX.1-2008中的其他任何功能都不需要async-cancel-safe。

     

如果某个线程启用了异步取消并且在执行非async-cancel-safe的函数时被取消,则行为未定义。

似乎无法终止单个pthread。来自section 2.4.3:

  

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

答案 2 :(得分:0)

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

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

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

当等待条件变量时,等待应该在循环内,而不是在简单的if语句中,因为虚假的唤醒。如果线程被唤醒,则无法保证,这是信号或广播呼叫的结果。

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