此问题称为Convoying:如果由于时间片中断或页面错误而导致持有锁的线程被调度,则所有其他线程必须等待。 https://en.wikipedia.org/wiki/Lock_(computer_science)#Disadvantages
众所周知,如果thread-1锁定了std::mutex
并且发生了thread-1的切换,并且如果此时许多线程(2,3,4 ...)想要锁定这个互斥锁,那么所有这些线程将被锁定,并将等待开启线程-1。
解决方法是使用无锁算法。但是如果要求使用互斥锁,这是避免这种情况的一些解决方案吗?
如何在即将到来之前预先找出100个周期 切换线程?
或者如何提前100个周期提前发出异常 在Linux x86_64上切换流程?
或者如何让线程继续工作一段时间(100 周期)
更新
我有20个CPU核心,我的程序有40个线程除以2个部分:
std::mutex mtx1
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部分,情况怎么会这样?