【发布时间】:2016-07-01 19:19:33
【问题描述】:
这个问题被称为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 部分:
-
第 1 部分 - 20 个线程使用受
std::mutex mtx1保护的第一个共享资源 -
第 2 部分 - 20 个线程使用受
std::mutex mtx2保护的第二个共享资源
众所周知,操作系统会为每个线程分配一定的工作时间,然后让他停止工作,并为下一个线程的空闲核心分配将运行相同时隙的内核。
第 1 部分: 有时,不经常,但这种情况对我来说很关键,发生 20 个线程中有 1 个执行 mtx1.lock() 然后开始使用共享资源,然后关闭操作系统(使该线程进入睡眠状态)mtx1.unlock() - 因为操作系统分配给该线程的时间已过期,操作系统决定让该线程进入睡眠状态。并且操作系统仅在 ~1 - 10 毫秒(30 000 000 个周期)后才打开该线程。在此期间,第 1 部分的 19 个其他线程至少一次尝试在 10 微秒(30 000 个周期)中的每个线程中获取共享资源,但mtx1 很忙。
然后,Part-1 的 19 个线程中的每一个都开始进入休眠状态,并且空闲的 CPU 内核被 Part-2 的线程占用。操作系统看到所有内核都处于忙碌状态,并且不会唤醒 Part-1 的线程。
这种情况并不经常发生,但是当这种情况发生时,第 1 部分(20 个线程)会冻结整个 1-10 毫秒(30 000 000 个周期),这对于任务来说是非常不可接受的。
第 1 部分的延迟超过 10 微秒(30 000 个周期)怎么会出现这种情况?
【问题讨论】:
-
如果线程正在等待锁,那么操作系统应该切换到下一个线程,并继续循环直到到达解锁互斥锁的线程。
-
我不确定我是否理解问题所在,因为在锁定线程运行时让所有其他线程阻塞正是使用互斥锁的关键。
-
“100 个周期”的相关性是什么——您能详细解释一下您的想法吗?
-
@Soren 如果我确定线程将在 100-1000 个周期后休眠,那么我确定我确定没有时间锁定互斥锁(标志的 CAS),完成工作并解锁互斥锁。在这个线程中
yield()立即休眠更有利可图。 -
@Galik 问题是我在 20 个内核上有 40 个线程,1 个线程锁定互斥锁并休眠,因为操作系统需要这个,还有 19 个线程等待这个互斥锁并休眠,20 个线程不使用这个互斥体占据了所有 20 个内核。
标签: c++ multithreading c++11 concurrency posix