为什么互斥需要原子操作?

我有以下互斥示例:

int mutex = 0;
   Thread A: 
   while(TRUE):
       while(mutex==1);
       #critical
       mutex=1;
    
   Thread B:
   int mutex = 0;
    while(TRUE):
       while(mutex==0);
       #critical
       mutex=0;

为什么这里的操作必须是原子的?也许在组装级别的场景将有助于理解。

比方说,我进入线程A并完成CS并设置互斥锁= 1。

MOV [MUTEX],1 

我的意思是这只是一条指令,这里出什么问题了?

iCMS 回答:为什么互斥需要原子操作?

MOV [MUTEX],1

可能会成功设置互斥锁,您怎么知道它是否已设置?好的,所以:

       LOCK:
1:            MOV R0,[MUTEX]
2:            MOV [MUTEX],1
3:            CMP R0,0
4:            BNE LOCK
5:            RET

这看起来好一点,但是如果在指令1之后但在指令2之前识别出中断,并且中断处理程序锁定了您想要的同一个互斥锁,该怎么办?稍后,它返回给您,现在[MUTEX] == 1,但您的R0 ==0。版本3:

       LOCK:
0:            DISABLE_INTERRUPTS
1:            MOV R0,0
4:            BNE LOCK
5:            RESTORE_INTERRUPTS
6:            RET

这一切都很好,直到我们添加了第二个不尊重已禁用中断的CPU。因此,您要么需要通常是不好的原子,要么需要检测冲突的方法。原子是无聊的,但是检测冲突有点酷:

LOCK:
        RESERVE [MUTEX] in Cache in a unique state.
        MOV R0,[MUTEX]
        STORE 1 to [MUTEX] only if it still in unique state.
        if [MUTEX] was not exclusive,jump to LOCK
        CMP R0,0
        BNE LOCK
        ret
 

因此,如果另一个处理器在处于[em> unique 状态时访问了[MUTEX],它将恢复为普通状态,从而向该处理器指示需要再次尝试。之所以采用这种方式,是因为它可以在任何类型的缓存一致性总线上运行,并且其类似物用于分布式数据库和其他方式的高级软件。这称为“加载/存储独占”,通常看起来更像是:

LOCK:
        LOAD.EXCL  R0,[MUTEX]
        STORE.EXCL R1,[MUTEX],1
        CMP R1,0       / R1 tells whether the store succeeded.
        BNE LOCK
        CMP R0,0       / R0 is the value we loaded earlier.
        BNE LOCK
        RET
本文链接:https://www.f2er.com/1890141.html

大家都在问