非无锁的std::atomic
对象通常使用一组锁(可能只是简单的自旋锁,但也可能是std::mutex)。如果是后者,你不希望两个相邻的互斥锁同时被使用,因此将它们全部打包在一起是很好的。
增加互斥锁的大小,是防止假共享的非常笨重的方法。如果一个实现想要确保 std::mutex 有一个自己的缓存行,那么它需要用 alignas(64)
声明它,以确保它的 alignof()
是这样的。这将强制填充使 sizeof(mutex) 成为 alignof 的倍数(在本例中相等)。
但请注意,如果你要固定一个大小,std::hardware_destructive_interference_size
在一些现代 x86-64 上应该是 128,因为 Intel 的 L2 缓存使用相邻线硬件预取。这是比同一缓存行更弱的破坏效应,而且这浪费了太多的空间。
alignas(std::hardware_destructive_interference_size) std::mutex mut;
std:mutex
只是一个被吹嘘的结构体,而结构体的默认最小对齐方式取决于其最大字段而不是整个结构体的大小;那么可以合理地假设sizeof(std:mutex)
几乎与最小对齐无关,甚至更少地表明了最佳对齐方式。相反,如果您想要64字节对齐,则无论结构体大小如何(例如使用类似于alignas(64)
的东西),都需要64字节对齐;并且sizeof()
大多无关紧要,应该使用std::alignment_of()
代替。 - Brendanalignof(mutex) = sizeof(mutex) = std::hardware_destructive_interference_size
或类似的设置,以确保互斥锁有自己的缓存行。(请注意,如果你要为其修复大小,则 hw_destructive_... 在某些现代 x86-64 上应该为 128,因为存在相邻行 HW prefetch) - Peter Cordes