简体   繁体   English

线程C ++中的瓶颈

[英]Bottleneck in Threads C++

So I am just trying to verify my understanding and hope that you guys will be able to clear up any misunderstandings. 所以我只是想验证我的理解,并希望你们能够解决任何误解。 So essentially I have two threads which use the same lock and perform calculations when they hold the lock but the interesting thing is that within the lock I will cause the thread to sleep for a short time. 所以基本上我有两个线程使用相同的锁并在他们持有锁时执行计算但有趣的是在锁内我将导致线程暂时休眠。 For both threads, this sleep time will be slightly different for either thread. 对于两个线程,这两个线程的睡眠时间会略有不同。 Because of the way locks work, wont the faster thread be bottlenecked by the slower thread as it will have to wait for it to complete? 由于锁的工作方式,更快的线程不会被较慢的线程瓶颈,因为它必须等待它完成?

For example: 例如:

Thread1() {

   lock();
   usleep(10)
   lock();

}

- -

Thread2() {

   lock();
   sleep(100)
   lock();

}

Now because Thread2 holds onto the lock longer, this will cause a bottleneck. 现在因为Thread2持有更长的锁,这将导致瓶颈。 And just to be sure, this system should have a back and forth happens on who gets the lock, right? 而且可以肯定的是,这个系统应该在谁获得锁定时来回发生,对吧?

It should be: 它应该是:

Thread1 gets lock
Thread1 releases lock
Thread2 gets lock
Thread2 releases lock
Thread1 gets lock
Thread1 releases lock
Thread2 gets lock
Thread2 releases lock

and so on, right? 等等,对吧? Thread1 should never be able to acquire the lock right after it releases it, can it? Thread1在发布之后永远不能获得锁定,可以吗?

Thread1 should never be able to acquire the lock right after it releases it, can it? Thread1在发布之后永远不能获得锁定,可以吗?

No , Thread1 could reacquire the lock, right after it releases it, because Thread2 could still be suspended (sleeps because of the scheduler) ,线程1 可以重新获取锁,将其释放之后,因为线程2仍然可以暂停 (睡觉,因为调度程序)

Also sleep only guarantees that the thread will sleep at least the wanted amount, it can and will often be more. sleep只能保证线程至少能够睡到想要的数量,它可以并且通常会更多。

In practice you would not hold a lock while calculating a value, you would get the lock, get the needed values for calculation, unlock, calculate it, and then get the lock again, check if the old values for the calculation are still valid/wanted, and then store/return your calculated results. 在实际操作中,您在计算值时不会保持锁定,您将获得锁定,获取所需的计算值,解锁,计算它,然后再次获取锁定,检查计算的旧值是否仍然有效/想要,然后存储/返回您的计算结果。 For this purpose, the std::future and atomic data types were invented. 为此,发明了std::future和atomic数据类型。

...this system should have a back and forth happens on who gets the lock, right? ......这个系统应该在谁获得锁定时来回发生,对吧?

Mostly The most of the time it will be a back and forth but some times there could/will be two lock/unlock cycles by Thread1. 大多数时候它会来回反复,但有些时候可能会/将会有两个锁定/解锁周期。 It depends on your scheduler and any execution and cycle will probably vary. 这取决于您的调度程序,任何执行和周期可能会有所不同。

Depending on what you are trying to achieve there are several possibilities. 根据您要实现的目标,有几种可能性。

If you want your threads to run in a particular order then have a look here . 如果您希望线程以特定顺序运行,请查看此处 There are basically 2 options: 基本上有两种选择:
- one is to use events where a thread is signaling the next one it has done his job and so the next one could start. - 一个是使用事件,其中一个线程正在发信号通知下一个线程完成了他的工作,因此下一个线程可以启动。
- the other one is to have a scheduler thread that handle the ordering with events or semaphores. - 另一个是有一个调度程序线程来处理事件或信号量的排序。

If you want your threads to run independently but have a lock mechanism where the order of attempting to get the lock is preserved you can have a look here . 如果你想让你的线程独立运行但是有一个锁定机制,其中保留了尝试获取锁定的顺序,你可以看看这里 The last part of the answer uses a queue of one condition variable per thread seem good. 答案的最后一部分使用每个线程一个条件变量的队列似乎很好。

And as it was said in previous answers and comments, using sleep for scheduling is a bad idea. 正如之前的答案和评论中所述,使用睡眠进行调度是一个坏主意。 Also lock is just a mutual exclusion mechanism and has no guarentee on the execution order. 锁也只是一种互斥机制,对执行顺序没有任何保证。 A lock is usually intended for preventing concurrent access on a critical resource so it should just do that. 锁通常用于防止对关键资源的并发访问,因此它应该这样做。 The smaller the critical section is, the better. 临界区越小越好。
Finally yes trying to order threads is making "bottlenecks". 最后是尝试订购线程是制造“瓶颈”。 In this particular case if all calculations are made in the locked sections the threads won't do anything in parallel so you can question the utility of using threads. 在这种特殊情况下,如果在锁定的部分中进行所有计算,则线程将不会并行执行任何操作,因此您可以质疑使用线程的效用。

Edit : 编辑:
Just on more warning: be careful, with threads it's not because is worked (was scheduled as you wanted to) 10 times on your machine that it always will, especially if you change any of the context (machine, workload...). 只是更多的警告:小心,使用线程并不是因为在你的机器上工作了10次(按照你的意愿)它总是会,特别是如果你改变任何上下文(机器,工作量......)。 You have to be sure of it by design. 你必须确保它的设计。

Absolutely nothing prevents either thread from immediately reacquiring the lock after releasing it. 绝对没有什么能阻止任何一个线程在释放后立即重新获得锁定。 I have no idea what you think prevents this from happening, but nothing does. 我不知道你的想法会阻止这种情况发生,但什么都没有。

In fact, in many implementations, a thread that is already running has an advantage in acquiring a lock over threads that have to be made ready-to-run. 实际上,在许多实现中,已经运行的线程在获取必须准备好运行的线程的锁定方面具有优势。 This is a sensible optimization to minimize context switches. 这是最小化上下文切换的合理优化。

If you're using a sleep as a way to simulate work and think this represents some real world issue with lock fairness, you are wrong. 如果您使用睡眠作为模拟工作的方式并认为这代表了锁定公平性的一些现实世界问题,那么您错了。 Threads that sleep are voluntarily yielding the remainder of their timeslice and are treated very differently from threads that exhaust their timeslice doing work. 睡觉的线程是自愿产生剩余的时间片,并且与处理工作时间耗尽的线程的处理方式截然不同。 If these threads were actually doing work, eventually one thread would exhaust its timeslice. 如果这些线程实际上正在工作,最终一个线程将耗尽其时间片。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM