Peterson算法中内存屏障的放置:屏障2是否可保障互斥性?
Peterson算法:内存屏障放在memory barrier2位置是否有效?
背景与问题
我近期在研究共享内存系统中的锁机制,学习了Peterson算法——这是一种能保证互斥性、实现线程安全进入临界区的经典方法。算法核心代码如下:
bool interested[2] = {false,false}; int turn; void enter(int me, int other) { interested[me] = true; //memory barrier 1 turn = me; //memory barrier 2 while(interested[other] && (turn == me)) ; } void exit(int me) { interested[me] = false; }
在多CPU共享资源的场景下,该算法会遭遇指令重排问题:单CPU环境中,指令重排会维持程序语义,但多CPU时,同一代码的执行顺序可能被打乱。比如某线程的CPU可能把turn = me的写操作提前到interested[me] = true之前执行,若此时发生上下文切换,另一线程会误以为当前线程还未申请进入临界区,从而直接进入,后续切换回原线程后,两个线程会同时处于临界区,彻底破坏互斥性。
内存屏障可以通过强制保障屏障前后的指令顺序来解决这类问题。资料显示将屏障放在标注为memory barrier2的位置(while循环前)可行,我初步也认为这个位置有效,因为它能确保数组更新先完成,现在想确认这个结论是否正确?
结论与分析
将内存屏障放在memory barrier2的位置完全有效,具体原因如下:
- 该位置的内存屏障会强制要求:屏障之前的两个写操作(
interested[me] = true和turn = me)必须在屏障之后的while循环读取操作(读取interested[other]和turn)之前完成执行,并且同步到所有CPU可见的共享内存中。 - 这就彻底阻断了CPU可能发生的、破坏互斥性的指令重排——不会再出现
turn = me先于interested[me] = true执行的情况。当另一线程检查interested[other]时,必然能看到当前线程已经标记了自己想要进入临界区的状态,从而正确进入循环等待逻辑,保证同一时刻只有一个线程进入临界区。
这个位置的内存屏障精准覆盖了需要保障顺序的指令边界,完美适配Peterson算法在多CPU环境下的正确性要求,和你的初步判断一致。
内容的提问来源于stack exchange,提问作者Thomas Stokes
相关产品推荐
相关产品推荐

