如何避免锁定(拥有)由睡眠的线程的互斥锁上的多个线程锁定?

时间:2016-07-01 19:19:33

标签: c++ multithreading c++11 concurrency posix

此问题称为Convoying:如果由于时间片中断或页面错误而导致持有锁的线程被调度,则所有其他线程必须等待。 https://en.wikipedia.org/wiki/Lock_(computer_science)#Disadvantages

众所周知,如果thread-1锁定了std::mutex并且发生了thread-1的切换,并且如果此时许多线程(2,3,4 ...)想要锁定这个互斥锁,那么所有这些线程将被锁定,并将等待开启线程-1。

解决方法是使用无锁算法。但是如果要求使用互斥锁,这是避免这种情况的一些解决方案吗?

  1. 如何在即将到来之前预先找出100个周期 切换线程?

  2. 或者如何提前100个周期提前发出异常     在Linux x86_64上切换流程?

  3. 或者如何让线程继续工作一段时间(100     周期)

  4. 更新

    我有20个CPU核心,我的程序有40个线程除以2个部分:

    • 第1部分 - 20个主题使用受std::mutex mtx1
    • 保护的第1个共享资源
    • 第2部分 - 20个主题使用受std::mutex mtx2保护的第2个共享资源

    众所周知,操作系统为每个线程提供了一定的工作时间,然后暂停了他,并给出了将运行相同时隙的下一个线程的空闲核心。

    第1部分:有时,不常见,但这种情况对我来说至关重要,发生20个线程中的1个执行mtx1.lock()然后开始使用共享资源然后操作系统切换 - 在完成mtx1.unlock()之前关闭(放入睡眠)这个线程 - 因为操作系统分配给这个线程和操作系统的过期时间量决定让这个线程休眠。并且OS仅在~1 - 10ms(30 000 000个周期)之后接通该线程。在此期间,Part-1的其他19个线程至少尝试过10次usec(30 000个周期)的共享资源,但mtx1正忙。

    然后, Part-1 的19个线程中的每一个都开始入睡,腾出的CPU核心被来自 Part-2 的线程占用。操作系统看到所有内核都很忙,并且没有唤醒 Part-1 的线程。

    这种情况并不经常发生,但是当发生这种情况时,Part-1(20个线程)会冻结整整1-10毫秒(30 000 000个周期),这对于任务来说是非常不可接受的。

    对于延迟超过10微秒(30 000个周期)的第1部分,情况怎么会这样?

1 个答案:

答案 0 :(得分:0)

无锁或无锁定设计的要点是,如果你确实需要一个互斥锁用于某些东西,那么这种情况很少见,因此任何两个线程碰到同一个互斥锁的可能性很小同时。

您对设计的解释以及您准备采取的对策听起来像您认为所有线程很可能都会碰到互斥锁 - 所以要么您的想法错了,要么您的设计错了。

您无法阅读调度程序的内容,但正如所讨论的here,您可以做的事情可能会影响thread scheduled的方式 - 但是我会建议不要那样玩。