【问题标题】:What happens if a thread in C tries to acquire a lock it already has?如果 C 中的一个线程试图获取它已经拥有的锁会发生什么?
【发布时间】:2018-04-25 01:54:27
【问题描述】:

所以假设有 1 个线程, 线程通过以下方式获取锁:

pthread_mutex_lock(&lock);

然后在解锁之前,再次到达一行是:

pthread_mutex_lock(&lock);

pthread库会阻塞线程的前进,还是会识别出线程已经持有锁,从而让它通过?

【问题讨论】:

  • 你试了有没有死机?
  • 你试过read some documentation吗?
  • 我已经尝试过做这些事情。但无法弄清楚,所以这就是我在这里问的原因。
  • @RayToal 尝试不是学习 C 的正确方法!!!
  • @MartinJames 如果文档说在某些情况下行为未定义,则试用不合适...

标签: c multithreading pthreads locking mutex


【解决方案1】:

行为取决于互斥体的种类。 POSIX standard 表示递归锁定行为取决于锁定的类型

如果线程尝试重新锁定它已经锁定的互斥体,pthread_mutex_lock() 的行为将如下表的重新锁定列中所述。

在 Relock 列中这样说

  • PTHREAD_MUTEX_NORMAL 类型的互斥锁可能会死锁
  • PTHREAD_MUTEX_ERRORCHECK 类型的互斥体应返回错误
  • PTHREAD_MUTEX_RECURSIVE 类型的互斥锁将用作递归锁,然后您必须解锁与锁定它一样多的次数
  • PTHREAD_MUTEX_DEFAULT 类型的互斥锁将具有未定义的行为,这实际上意味着如果在该平台上默认锁是前 3 种类型中的任何一种,它的行为将与列中的特征一样上面,如果是其他类型,那么行为将是未定义的。

因此,测试 PTHREAD_MUTEX_DEFAULT 锁以找出行为是什么特别没有意义。

Linux manuals pthread_mutex_lock(3) 改写如下:

如果互斥锁已经被调用线程锁定, pthread_mutex_lock 的行为取决于 一种互斥体。如果互斥锁属于 fast kind,调用线程被挂起,直到互斥体 被解锁,从而有效地导致调用 线程死锁。如果互斥体是 错误 检查种,pthread_mutex_lock 立即返回错误代码EDEADLK。如果互斥锁是 递归类型,pthread_mutex_lock 成功并立即返回,记录数字 调用线程锁定互斥锁的次数。一个 相同数量的pthread_mutex_unlock 操作必须 在互斥体返回解锁之前执行 状态。

根据文档,在 Linux 中,默认类型是 fast,但您不能依赖它是可移植的。

【讨论】:

    【解决方案2】:

    POSIX 在几个变体中支持许多不同的互斥体类型。都使用相同的pthread_mutex_t 类型,因此无法知道pthread_mutex_lock 在重新锁定当前线程已经获取的锁时做了什么。

    常见的行为包括:

    • 常规互斥锁的自死锁(pthread_mutex_lock 永不返回)。
    • 错误检查互斥体的错误(pthread_mutex_lock 返回错误代码)。
    • 锁定操作成功,在锁定可用于其他线程进行锁定(递归互斥锁)之前,还需要进行一次解锁操作。

    在使用pthread_mutex_init 使用属性创建互斥锁时,可以选择互斥锁行为;见pthread_mutexattr_init。一些系统还提供非标准的初始化器,例如标准的 PTHREAD_MUTEX_INITIALIZER ,它可以创建不同的变体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-16
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 2019-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多