for循环内外的互斥锁速度差异

Posted

技术标签:

【中文标题】for循环内外的互斥锁速度差异【英文标题】:Mutex lock speed difference inside and outisde the foor loop 【发布时间】:2017-05-22 18:12:51 【问题描述】:

我对在 for 循环内部和外部使用互斥锁 lock() 和 unlock() 的速度不同感到困惑。我得到了一个全局变量值和一个将其递增 1000000 次的函数。该函数由 5 个线程并行运行。我测量了经过的时间并得到了这些结果:

    mutex.lock();
    for(int i = 0; i < 1000000; i++)
    
        value++;
    
    mutex.unlock();

0.160921 秒

和:

    for(int i = 0; i < 1000000; i++)
            
        mutex.lock();
        value++;
        mutex.unlock();
    

2.10521 秒

我假设使用第二个内部互斥体安排控制太精细了,并且在线程切换之间花费了大量时间?还是有别的?

【问题讨论】:

【参考方案1】:

锁定和解锁互斥体需要一些时间。具体来说,它比增加一个整数需要更多的时间。您的第二个示例只是测试锁定/解锁速度,并且还增加了任务切换开销,因为在互斥锁解锁的任何时候,不同的线程都可以接管。

首先,编译器可以通过一个加法来替换循环。而且因为线程的全部功能都被互斥体覆盖,所以没有并行执行;除了一个线程之外的所有线程都被阻塞,直到一个线程的循环完成,这意味着代码相当于在一个线程上连续循环五次。

这与细粒度锁定与粗粒度锁定关系不大。这些策略是关于您是否拥有覆盖大量资源的少量锁,或者覆盖少量资源的大量锁。您只有一种资源(全局 int),因此无需做出决定。

相反,这是关于是否仅将互斥锁锁定一小段时间,从而在其余时间将其打开以供其他线程工作,或者将其锁定更长的时间以避免开销,但会降低并行度。但是,由于您的线程除了访问受保护的资源之外什么都不做,因此没有“其余时间”。您的问题(将整数递增 5000000 次)一开始就没有内在的并行性,因此没有什么可供多线程利用的。

【讨论】:

以上是关于for循环内外的互斥锁速度差异的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中使用互斥锁和屏障进行线程同步

互斥锁与进程间通信

打开与服务共享的互斥锁

如何在 C++ 中正确地在循环中使用互斥锁?

图解Go里面的互斥锁mutex了解编程语言核心实现源码

带有对象的互斥锁