【问题标题】:Automatically releasing mutexes held when thread destructor runs线程析构函数运行时自动释放互斥锁
【发布时间】:2012-07-30 19:38:30
【问题描述】:

当线程退出(在其析构函数中)时,是否有一种万无一失的方法来自动释放线程持有的互斥锁?

我一直采取的方法是为每个互斥体创建一个结构,该结构体持有持有它的线程的身份,然后在析构函数中扫描此列表,如果有任何互斥体与正在完成的线程匹配,则释放那么它。但我认为这实际上有一个竞争条件:如果在我锁定互斥锁之后但在我设置数据结构之前调用析构函数会发生什么?

我还查看了 pthread_mutexattr_setrobust_np,但我的理解是 np 函数是不可移植的,我过去曾遇到过这样的问题。

作为参考,每个线程都与一个 TCP/IP 连接相关联,并且锁定/解锁是为了响应此连接上的请求而发生的。如果连接异常关闭,我需要清理,即释放所有持有的锁。

【问题讨论】:

  • “但我认为这实际上有一个竞争条件:如果在我锁定互斥体之后但在我设置数据结构之前调用析构函数会发生什么?” - 那么听起来你甚至在尝试向互斥体添加跟踪之前就已经有了竞争条件。如果您在对象上调用析构函数,而它可能正在另一个线程上使用,则会出现问题。
  • 好吧,如果我在 pthread_mutex_lock 中的线程上调用 pthread_kill,在析构函数中,锁将被持有或不持有,因为获取锁是原子操作。

标签: pthreads mutex unlock


【解决方案1】:

我找到了一个似乎可行的解决方案。首先,我使用错误检查互斥体(PTHREAD_ERRORCHECK_MUTEX_INITIALIZERPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)。

接下来,在析构函数中,我尝试解锁所有互斥锁,其想法是任何不属于线程的互斥锁都将被单独保留,但线程拥有的任何互斥锁都将被释放。

由于某种原因,即使线程拥有的互斥锁也会返回 EPERM,但随后尝试从另一个线程重新锁定互斥锁会成功,而如果不尝试解锁另一个尝试,则会死锁。反之,在析构函数运行后,其他不属于被析构线程的互斥体仍然会被锁定。

【讨论】:

  • 您是说 dtor 与获取互斥锁的线程在同一线程上运行吗?如果是这样,那么在解锁互斥锁时获得EPERM 表明事情不在您认为的状态。线程如何在没有释放互斥锁的情况下到达 dtor?您可能需要研究取消点和取消清理处理程序。
  • 我假设它确实如此。当我从析构函数调用 pthread_self() 时,它返回我期望从线程中得到的值。线程在到达析构函数之前没有释放互斥锁的原因是互斥锁是由客户端在 TCP 连接上的请求获取的。 (客户端实际上得到了一个锁,但是锁是根据互斥锁实现的)如果连接在客户端释放之前就死掉了,我们必须以某种方式清理(释放锁)。
  • 我也一直在研究清理处理程序,但我不确定如果它们不在与互斥锁相同的范围内完成,它们会如何工作,即它们需要完成在线程的顶层,而互斥锁可以发生在任何级别的函数嵌套。
  • 如果 dtor 正在(并且总是)在获取互斥锁的线程的上下文中运行,那么在尝试为互斥锁添加跟踪信息时不会出现竞争条件,如您在这个问题。线程不能与自己竞争(这就是为什么单线程程序不需要担心它们)。
  • 我相信竞争条件是针对试图杀死它的线程,而不是针对它自己
猜你喜欢
  • 2015-03-21
  • 2011-05-08
  • 1970-01-01
  • 2022-08-14
  • 2011-03-17
  • 1970-01-01
  • 2010-12-25
  • 2012-02-23
  • 2021-01-29
相关资源
最近更新 更多