所以我只是想验证我的理解,并希望你们能够解决任何误解。所以基本上我有两个线程使用相同的锁并在他们持有锁时执行计算但有趣的是在锁内我将导致线程暂时休眠。对于两个线程,这两个线程的睡眠时间会略有不同。由于锁的工作方式,更快的线程不会被较慢的线程瓶颈,因为它必须等待它完成?
例如:
Thread1() {
lock();
usleep(10)
lock();
}
-
Thread2() {
lock();
sleep(100)
lock();
}
现在因为Thread2持有更长的锁,这将导致瓶颈。而且可以肯定的是,这个系统应该在谁获得锁定时来回发生,对吗?
应该是:
Thread1 gets lock
Thread1 releases lock
Thread2 gets lock
Thread2 releases lock
Thread1 gets lock
Thread1 releases lock
Thread2 gets lock
Thread2 releases lock
等等,对吧? Thread1在释放之后永远不能获得锁定,可以吗?
答案 0 :(得分:1)
Thread1永远不能在释放后立即获取锁定,是吗?
否,Thread1 可以重新获取锁定,在它发布之后,因为Thread2仍然可以暂停(由于调度程序而休眠) )
同样sleep
只保证线程能够至少所需的金额,它可以并且通常会更多。
实际上,在计算值时你不会持有锁,你会获得锁定,获得所需的计算值,解锁,计算它,然后再次获得锁定,检查计算的旧值是否为仍然有效/想要,然后存储/返回您的计算结果。
为此,发明了std::future
和原子数据类型。
......这个系统应该在谁获得锁定时来回发生,对吗?
主要大部分时间它来回反复,但有时可能/将会有两次锁定/解锁循环。这取决于您的调度程序,任何执行和周期可能会有所不同。
答案 1 :(得分:0)
根据您想要实现的目标,有几种可能性。
如果您希望线程按特定顺序运行,请查看here。
基本上有两种选择:
- 一种是使用线程发出下一个线程的事件,然后下一个线程就可以开始了
- 另一个是有一个调度程序线程来处理事件或信号量的排序。
如果您希望线程独立运行但具有锁定机制,其中保留了尝试获取锁定的顺序,您可以查看here。答案的最后一部分使用每个线程一个条件变量的队列似乎很好。
正如之前的答案和评论所说,使用睡眠进行调度是一个坏主意。 锁也只是一种互斥机制,对执行顺序没有任何保证。 锁通常用于防止对关键资源的并发访问,因此它应该这样做。临界区越小越好 最后是尝试订购线程正在制造"瓶颈"。在这种特殊情况下,如果所有计算都是在锁定的部分进行的,则线程不会并行执行任何操作,因此您可以质疑使用线程的效用。
编辑:
只是更多的警告:小心,线程不是因为在你的机器上工作了10次(按照你的意愿),它总是会,特别是如果你改变任何上下文(机器,工作量)。 ..)。你必须通过设计确定它。
答案 2 :(得分:0)
绝对没有什么能阻止任何一个线程在释放后立即重新获取锁定。我不知道你的想法会阻止这种情况发生,但什么也没有。
事实上,在许多实现中,已经运行的线程在获取必须准备好运行的线程的锁定方面具有优势。这是最小化上下文切换的合理优化。
如果您使用睡眠作为模拟工作的方式并认为这代表了锁定公平性的一些现实世界问题,那么您错了。睡觉的线程是自愿产生剩余的时间片,并且与处理工作时间耗尽的线程的处理方式截然不同。如果这些线程实际上正在工作,最终一个线程会耗尽其时间片。