在多处理器的情况下理解原子锁操作的问题

时间:2016-06-25 12:39:21

标签: multithreading synchronization locking mutex atomic

在单处理器的情况下,我们在执行锁定操作(锁定获取,锁定释放)之前禁用中断以防止上下文 切换,然后在操作后我们重新启用它。

但是,对于多处理器CPU,只是禁用中断不足以使锁定操作成为原子。

我从一个消息来源读到, "它发生在每个处理器都有一个缓存时,即使中断被禁用,它们也可以写入同一个内存。"

Q1。为什么在原子锁操作的情况下这甚至是重要的?

Q2。在仅在禁用中断的情况下在多处理器环境中实现锁定操作时会出现哪些其他问题?

1 个答案:

答案 0 :(得分:0)

仅禁用中断是不够的,因为在多处理器上运行的线程仍然可以同时访问同步对象的函数内的数据结构和代码,因此仅通过禁用中断就无法实现原子性。

例如,让L为LOCK对象,而L.status为" FREE" X是具有四个线程T1,T2,T3,T4的过程,并且它们中的每一个在分开的处理器P1,P2,P3,P4上运行。

让我们假设LOCK :: acquire()的伪代码如下,

 LOCK::acquire(){
       if(status==BUSY){
           lock.waitList.add(RunningThread);
           TCB t == readyList.remove(); 
           thread_switch(RunningThread,t);
           t.state=running;    

        }
       else{
          status=BUSY; 
       }


}

如果我们只禁用中断,T1,T2,T3,T4的代码仍然可以在相应的处理器上运行。让我们假设锁定在一刻是免费的。

如果所有线程同时尝试获取lock-L,则可能它们可能最终同时检查锁的状态,在这种情况下,每个线程都会找到状态==" FREE",并且每个线程都将获得锁,这将消除当前锁实现的适用性。

这就是为什么在为多处理器实现锁定对象时使用不同的原子操作,例如test_and_set。这些原子操作只允许来自一个多处理器的一个线程一次访问锁定的代码。