使用专门设计的自旋锁(例如http://anki3d.org/spinlock),与像这样的代码相比,有哪些好处:
std::mutex m;
while (!m.try_lock()) {}
# do work
m.unlock();
使用专门设计的自旋锁(例如http://anki3d.org/spinlock),与像这样的代码相比,有哪些好处:
std::mutex m;
while (!m.try_lock()) {}
# do work
m.unlock();
在典型的硬件上,有巨大的好处:
您的“伪自旋锁”可能会使CPU总线饱和,导致CPU自旋,使其他物理核心(包括持有锁的物理核心)挨饿。
如果CPU支持超线程或类似功能,您的“伪自旋锁”可能会消耗过多的执行资源,使共享该物理核心的另一个线程挨饿。
您的“伪自旋锁”可能会进行不必要的写操作,导致缓存行为变糟。当您在x86 / x86_64 CPU上执行读修改写操作时(比如尝试锁定的compare / exchange操作可能会执行的操作),即使值没有改变,也会执行写入。这个写操作会使其他核心上的缓存行失效,需要在另一个核心访问该行时重新共享该行。如果其他核心上的线程同时竞争同一把锁,则情况非常糟糕。
您的“伪自旋锁”与分支预测交互不良。当您最终获得锁时,在锁定其他线程并需要尽快执行的点上,您会进行所有错误的预测分支。这就像一名跑步者在起跑线准备好奔跑,但当他听到起始枪声后,他停下来喘口气。
基本上,该代码做的一切都是自旋锁可能做错的事情。没有任何东西被有效地处理。编写良好的同步原语需要深入的硬件专业知识。
std::mutex
的另一个非技术原因可能是许可条款。许可条款是设计决策的不充分理由,但它们可能仍然非常真实。
m.lock();
?忙等待有什么意义吗? - Igor Tandetniktry_lock()
的成本与lock()
相当,而您正在承受最坏的情况 - 既需要花费访问内核的代价,又会使用 CPU 作为加热器。 - Igor Tandetnik