【问题标题】:Why is unlocking an unlocked std::mutex UB?为什么要解锁未锁定的 std::mutex UB?
【发布时间】:2021-10-30 12:28:20
【问题描述】:

解锁未锁定的std::mutex 是UB。为什么会这样?为什么它只是没有效果,因为互斥体尚未锁定,或者已经解锁,那么再次调用解锁有什么害处?

【问题讨论】:

  • 你不是在问为什么解锁一个未锁定的std::mutex 是UB,你是在问std::mutex 是如何工作的,std::mutex 是如何实现的。

标签: c++ c++11 parallel-processing std mutex


【解决方案1】:

解锁未锁定的 std::mutex 是 UB。为什么会这样?为什么不只是没有效果,因为互斥体还没有锁定,或者已经解锁,那么再次调用解锁有什么坏处?

因为那是有代价的。这将要求每个实现都包含必要的内部检查以确保这种行为。

如果您想要一个具有这种行为的互斥锁,您可以编写一个代码。但是,您必须支付额外支票的费用才能执行此操作。但是,不需要这种行为的人不会支付这些费用。

成本往往比您想象的要高。拥有互斥锁可以安全地访问受该互斥锁保护的所有内容。如果您没有互斥锁,则访问受该互斥锁保护的东西是不安全的。因此,在某些实现中,这可能需要等效于获取互斥锁(以便您可以安全地访问互斥锁的所有权数据),然后才能释放互斥锁。如果获取和释放互斥锁的成本相当,这可能会使解锁互斥锁的成本翻倍。呸。

【讨论】:

    【解决方案2】:

    这是历史性的。
    可以从semaphores 实现互斥锁。在这个实现中,Unlocking 增加一个计数,锁定测试它不为零,然后减少它。 (如果没记错的话,您需要另一个信号量来锁定“测试”位 - 但对于这个问题,我将忽略它)。互斥锁的唯一有效值是 0(锁定)或 1(解锁)。 通过锁定已锁定的互斥体,或解锁未锁定的互斥体,您可以将值驱动到 0-1 范围之外,从而使互斥体不再正确执行。
    它是 U/B,因为可以制作不受此问题影响的互斥锁,但并非每个系统都可以访问这种解决方案,因此如果您想要可移植的 C++ 代码,您必须有一个心智模型增加/减少的简单计数,并且仅锁定或未锁定的互斥锁。仅解锁已锁定的互斥锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-17
      • 2021-06-04
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 2012-10-24
      • 2016-05-21
      相关资源
      最近更新 更多