为什么 Spinlock 的第二次旋转可以提升性能?

Edu*_*yan 17 c++ performance atomic

这是一个用 实现的基本自旋锁std::atomic_flag该书
的作者声称第二次可以提高性能。lock()

class Spinlock
{
    std::atomic_flag flag{};
public:
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire)) {
            while (flag.test(std::memory_order_acquire)); //Spin here
        }
    }
    void unlock() {
        flag.clear(std::memory_order_release);
    }
};
Run Code Online (Sandbox Code Playgroud)

test()我们在额外的内部循环中 使用的原因是性能:test()不会使缓存行无效,而test_and_set()会使。

有人可以详细解释一下这个报价吗?测试还是读操作,需要从内存中读取对吗?

Yak*_*ont 19

读取内存地址不会清除缓存行。

写作确实如此。

所以在现代计算机中,有RAM,并且在CPU“周围”有多层缓存(它们被称为L1、L2和L3缓存,但重要的是它们是层,而CPU位于中间) )。在多核系统中,外层通常是共享的;最内层通常不是,并且特定于给定的CPU。

清除缓存行意味着通知持有该内存的所有其他缓存“您拥有的数据可能已过时,将其扔掉”。

测试和设置写入 true 并自动返回旧值。它会清除缓存行,因为它会写入。

测试不写。如果您有另一个线程与此线程不同步,则不必戳它读取该内存的缓存。

外层循环写入 true,如果替换为 false,则退出。内循环等待,直到出现错误可见,然后进入外循环。内部循环不需要清除所有其他 cpu 的原子标志值的缓存状态,但外部循环必须清除(因为它可以将 false 更改为 true)。由于旋转可能会持续一段时间,因此避免连续清除缓存似乎是个好主意。