gpt4 book ai didi

c++ - 互斥锁如何在低级别等待解锁?

转载 作者:搜寻专家 更新时间:2023-10-30 23:54:55 24 4
gpt4 key购买 nike

我想知道互斥量(或其他锁定实现)如何实现锁定功能的等待功能。我的意思是,是一条 cpu 指令对 mutex.lock 调用进行排队,是仅在操作系统中实现还是什么?

在我做的测试中,我认为这个等待功能只在操作系统层完成,并且创建了某种旋转,检查锁是否可以继续,如果没有则让线程休眠。是吗?

非常感谢。

最佳答案

它依赖于平台。通常有一个自旋锁部分,如果达到固定的自旋限制,它会回退到操作系统中的阻塞。

自旋锁通常是通过在解锁互斥量时读取包含特定值的内存地址来实现的。如果它被视为未锁定,则会尝试将该值从未锁定值自动更改为锁定值。如果该原子交换成功,则互斥锁被锁定。通常会计算旋转次数,如果达到限制,我们会切换到操作系统中的阻塞。

操作系统中的 block 通常以大致相同的方式实现,只是线程不是休眠,而是将自己添加到等待锁的列表中。当一个线程释放锁时,它会检查操作系统中是否有任何东西在等待,如果有,就解除阻塞。这会导致操作系统调度该线程。然后它通常会尝试执行自旋锁会尝试执行的相同原子交换,如果失败则再次在操作系统中阻塞。

在伪代码中:

锁定:

  1. 检查内存位置以查看锁是否已锁定。如果是,请转到第 3 步。
  2. 尝试自动将内存位置从解锁状态切换到锁定状态。如果我们成功了,停止,我们持有锁。
  3. 增加旋转计数。如果我们没有旋转太多次,转到步骤 1。
  4. 以原子方式增加等待此锁的线程数。
  5. 尝试自动将内存位置从解锁状态切换到锁定状态。如果我们成功,减少等待线程的数量并停止,我们持有锁。
  6. 在操作系统中有条件地阻止。
  7. 转到第 5 步。

解锁:

  1. 以原子方式将保持锁定状态的内存位置设置为未锁定。
  2. 如果操作系统中等待此锁的线程数大于零,则告诉操作系统解除阻塞等待此锁的所有线程。

请注意,操作系统必须实现某种机制来避免竞争,即解除阻塞操作系统中等待的任何线程的请求恰好发生在线程设法阻塞之前。该方法因操作系统而异。例如,Linux 有一种叫做“futex”的东西,它本质上是一种以原子方式实现锁定伪代码的第 4、5 和 6 步的方法。

警告:如果您尝试在代码中实现此算法,请了解您可能会生产出性能几乎不如正确实现的玩具。您需要深入的、特定于平台的知识来避免您可能掉入的令人讨厌的性能陷阱。例如,很容易编写一个自旋锁,使其从另一个线程中窃取核心执行资源,该线程与超线程共享 CPU 中的物理内核。并且很容易编写成功交换的代码,以便 CPU 的分支预测预测它将失败,并且当您获得锁时,您将承受可怕的分支预测错误惩罚。

关于c++ - 互斥锁如何在低级别等待解锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34517544/

24 4 0