c++ - 在一个代码块中多次互斥锁定一个变量,还是只锁定整个代码块,效率更高?

标签 c++ mutex

如果我们有如下代码示例:

if (letsDoThis) //bool
{
    sharedVar++; // This is shared across other threads.
          :
    sharedVar++;
          :
    sharedVar++;
          :
    sharedVar++;
          :
    sharedVar++;
}

其中每个 : 大约是 10 行代码(没有缓慢的函数调用或任何东西)。编写代码以便在整个“if” block (好吧,if block 的内容)周围锁定一个互斥体,或者锁定和解锁每个单独的 sharedVar 用法会更快吗?

如果这是一个“视情况而定”类型的问题,那么哪种方法(也许作为经验法则)更好?

最后,您如何确定两者中哪一个在您的系统上运行得更快? - 跟踪工具真的会以有意义的方式向您显示有用的数据吗?

最佳答案

这取决于(在所有其他影响性能的因素中)

  • 您有多少线程和核心(两者的最小值相关)
  • 线程在该部分代码(以及锁定互斥体的其他部分)花费了多少时间

从单个线程的角度来看,多个锁定和解锁意味着额外的工作,并且 - 特别是在拥塞的情况下 - 相当昂贵/耗时,并且它可能会导致内核之间更多的缓存乒乓。所以会降低单线程的性能。但是,如果多次锁定和解锁减少了线程在每次迭代中持有互斥锁的总时间,那么这意味着您的程序中可以有更多的并行性,并且整体性能会随着线程和 CPU 内核的数量而更好地扩展。

这两种影响都可以忽略不计,两种影响都可能很重要,如果代码不在您程序的热路径中,那么一开始它可能并不重要。我认为,您唯一可以做的就是运行两种变体并测量整体吞吐量,以确定在您的情况下什么更好。如果您看不出有什么区别,为了简单起见,我可能会使用单锁和解锁(即使用 std::lock_guard)。

然而,您应该问的一般问题是,如果您真的需要在线程之间进行如此多的同步,并且您是否必须多次同步:如果其他线程看不到共享状态的中间值(这如果它们不互相等待,你无论如何都无法保证),那你为什么不将共享状态上的所有操作组合起来,并在 block 的末尾使其成为一个单一的操作?

当然,如果您的共享状态确实只是一个整数,那么您应该只使用原子并完全摆脱互斥量。

关于c++ - 在一个代码块中多次互斥锁定一个变量,还是只锁定整个代码块,效率更高?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36443386/

相关文章:

c++ - 如何停止嵌套的 for 循环

c++ - 对重载函数的模糊调用 - int 和 int&

c++ - 标准 C++ 中的共享递归互斥锁

子进程无法获取共享内存区域中的互斥锁

c++ - 使用互斥锁在 C++ 中复制构造函数

c - 互斥量不适用于两个正在运行的进程

c++ - 在 CMake 项目中链接静态库 - 未定义的引用

c++ - Microsoft Visual Studio 发现我的所有 CUDA 设备端函数都存在错误

C++ : Modifying a timer

c++ - 免费互斥问题