【问题标题】:What is the `pthread_mutex_lock()` wake order with multiple threads waiting?多线程等待的“pthread_mutex_lock()”唤醒顺序​​是什么?
【发布时间】:2013-02-03 12:38:02
【问题描述】:

假设我在调用pthread_mutex_lock() 时有多个线程阻塞。当互斥锁可用时,调用pthread_mutex_lock() 的第一个线程是否获得锁?也就是说,是否按 FIFO 顺序调用 pthread_mutex_lock()?如果不是,它们的顺序是什么(如果有的话)?谢谢!

【问题讨论】:

    标签: c multithreading pthreads


    【解决方案1】:

    当互斥体可用时,调用pthread_mutex_lock() 的第一个线程是否获得锁?

    没有。其中一个等待的线程获得了锁,但不确定是哪一个。

    先进先出顺序?

    FIFO 互斥体已经是一种模式。见Implementing a FIFO mutex in pthreads

    【讨论】:

    • FIFO 我的意思是第一个调用pthread_mutex_lock 的线程,当它可用时第一个获得锁,以此类推后续线程。猜猜我正在实施我自己的。谢谢。
    • @shanet: “我的意思是第一个调用 pthread_mutex_lock 的线程在可用时第一个获得锁” - 是的,这正是 FIFO 互斥锁的含义关于。
    【解决方案2】:

    “如果调用pthread_mutex_unlock()时mutex引用的mutex对象上有线程阻塞,导致mutex可用,调度策略将决定哪个线程获取mutex。”

    除此之外,POSIX 标准并未指定您的问题的答案。根据实现的选择,它可能是随机的,也可能是 FIFO 或 LIFO 或任何其他顺序。

    【讨论】:

      【解决方案3】:

      FIFO 排序可能是效率最低的互斥唤醒顺序。只有真正糟糕的实现才会使用它。最近运行的线程可能能够在没有上下文切换的情况下再次运行,并且最近运行的线程,其更多的数据和代码将在缓存中处于热状态。合理的实现会尝试将互斥锁分配给大多数时间最近持有它的线程。

      考虑执行此操作的两个线程:

      1. 获取互斥体。
      2. 调整一些数据。
      3. 释放互斥锁。
      4. 转到步骤 1。

      现在想象两个线程在单核 CPU 上运行此代码。应该清楚的是,FIFO 互斥行为会导致每次上下文切换都“调整一些数据”——这是最坏的结果。

      当然,合理的实现通常确实对公平性有所帮助。我们不希望一个线程没有任何进展。但这很难证明 FIFO 实现的合理性!

      【讨论】:

      • 您对“合理”的看法与大多数人不兼容。特别是它与实时要求不兼容;快速锁定和解锁互斥锁的单个线程将阻止任何其他线程的前进。每个优先级中的 FIFO 顺序是互斥锁应该表现的正常方式,以实现稳健的实时使用。
      • @R.. POSIX 互斥锁不是,也不打算是实时的。它们旨在最大限度地推动整个过程的向前进展,而不会明显不公平。
      • Per POSIX,“pthread_mutex_unlock() 函数应释放互斥锁引用的互斥锁对象。释放互斥锁的方式取决于互斥锁的类型属性。如果有线程阻塞在互斥锁上调用 pthread_mutex_unlock() 时互斥锁引用的对象,导致互斥锁可用,调度策略应确定哪个线程应获取互斥锁。" (强调我的)
      • 顺便说一句,当 POSIX 互斥体具有优先级继承协议和优先级上限,以及专为实时使用而设计的功能时,我认为您几乎不能说它们不是实时的。
      • @R..:我说的是默认互斥锁,我认为这是 OP 所要求的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 2021-08-09
      • 2010-10-29
      • 1970-01-01
      相关资源
      最近更新 更多