assembly CAS指令如何保证原子性

h4cxqtbf  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(183)

根据Wiki,CAS做这样的事情:

function cas(p : pointer to int, old : int, new : int) returns bool {
    if *p ≠ old {
        return false
    }
    *p ← new
    return true
}

嗯,在我看来,如果多个处理器将尝试使用相同的参数执行CAS指令,则可能会同时进行多个写入尝试,因此无论如何这样做都不安全。
我哪里错了?

8qgya5xd

8qgya5xd1#

来自多个内核的原子读-比较-写指令(在同一高速缓存线上)* 确实 * 会相互竞争,但这取决于硬件来解决。Hardware arbitration of atomic RMW instructions是现代CPU中的一个真实的的东西,它提供了一定程度的公平性,因此lock cmpxchg上的一个线程不会完全阻止其他线程执行相同的操作。
(尽管这是一个糟糕的设计,除非your retry could succeed without waiting让另一个线程修改任何东西,例如,实现fetch_oror similar的重试循环可以使用expected的更新值再次尝试。但是,如果等待锁或标志更改,在初始CAS失败后,it's better将在获取或释放负载上旋转,并且仅在CAS可能成功时执行CAS。)
没有人能保证它们发生的顺序,这就是为什么你需要仔细设计你的算法,以便正确性只依赖于原子的比较和交换。(ABA problem是一个常见的陷阱)。
顺便说一句,整个伪代码块作为单个原子操作发生。对于硬件来说,使读-比较-写或读-修改-写作为单个原子操作发生比仅仅存储要困难得多,MESIF/MOESI处理得很好。
您确定吗?我认为这样做是不安全的,因为,例如,x86不能保证对非对齐DWORD的写操作的原子性
lock cmpxchg使操作原子化,而不管是否对齐。对于未对齐的操作,它可能会慢很多,尤其是在高速缓存行拆分时,原子化修改单个高速缓存行是不够的。
另请参见x86上的原子性,我在其中解释了原子操作的含义。

nvbavucw

nvbavucw2#

如果你读过wiki,它会说CAS是你发布的代码的“以下伪代码的原子版本”。原子意味着代码将在没有其他线程中断的情况下执行。因此,即使多个线程试图使用相同的参数同时执行这段代码(就像你建议的那样)只有一个返回true,因为实际上它们不会同时执行,因为原子性要求它们独立运行。
由于您提到“x86不保证对非对齐DWORD的写入的原子性”,这在这里也不是问题,因为cas函数的原子属性。

相关问题