【问题标题】:Understanding issues with atomic lock operations in case of multi processors了解多处理器情况下的原子锁操作问题
【发布时间】:2016-06-25 12:39:21
【问题描述】:
在单处理器的情况下,我们在执行锁定操作(锁定获取,锁定释放)之前禁用中断以防止上下文
切换,然后在操作后我们重新启用它。
但是,在多处理器 CPU 的情况下,仅禁用中断不足以使锁定操作原子化。
我从一个来源读到,
“这是因为每个处理器都有一个缓存,即使中断被禁用,它们也可以写入相同的内存。”
第一季度。为什么在原子锁操作的情况下这甚至很重要?
第二季度。在仅禁用中断的多处理器环境中实现锁定操作时会出现哪些其他问题?
【问题讨论】:
标签:
multithreading
synchronization
locking
mutex
atomic
【解决方案1】:
仅仅关闭中断是不够的,因为运行在多处理器上的线程仍然可以同时访问同步对象函数内部的数据结构和代码,因此仅仅关闭中断并不能实现原子性。
例如,假设 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。这些原子操作一次只允许一个线程来自一个多处理器访问锁的代码。