如何实现锁定



我有以下代码:

 while(lock)
      ;   
 lock = 1;
 // critical section
 lock = 0;

由于读取或更改锁定值本身就是多指令

read lock
change value
write it

如果发生如下情况:

1) One thread reads the lock and stops there
2) Another thread reads it and sees it is free; lock it and do something untill half
3) First thread wakes up and goes into CS

那么如何在系统中实施锁定?将变量放在另一个变量之上是不对的:这就像守卫一样?

停止其他处理器线程也不对?

它是 100% 特定于平台的。通常,CPU提供某种形式的原子操作,例如交换或比较和交换。典型的锁可能如下所示:

1) 创建:在变量中存储 0(解锁)。

2) 锁定:以原子方式尝试将变量的值从 0(解锁)切换到 1(锁定)。如果我们失败了(因为它一开始没有解锁),让 CPU 休息一下,然后重试。使用内存屏障来确保将来的内存操作不会潜入此屏障后面。

3)解锁:使用内存屏障来确保以前的内存操作不会偷偷溜过这个。以原子方式将 0(解锁)写入变量。

请注意,除非您想要设计自己的同步基元,否则您实际上不需要了解这一点。如果你想这样做,你需要了解更多。对于每个程序员来说,对他正在使硬件做什么有一个大致的了解当然是一个好主意。但这是一个充满严重重魔法的区域。有很多很多方法可能会发生可怕的错误。因此,只需使用由制作平台、编译器和线程库的天才提供的锁定原语。这里是龙。

例如,SMP 奔腾 Pro 系统有一个错误,需要在解锁操作中进行特殊处理。锁定算法的朴素实现将导致分支预测逻辑期望操作继续旋转,从而在最糟糕的时间(首次获取锁时)产生巨大的性能损失。锁定算法的朴素实现可能会导致两个内核分别等待同一锁使总线饱和,从而减慢需要完成工作的 CPU 速度,以便将锁释放到爬行状态。这些都需要大量的魔法和对硬件的深刻理解来处理。

在我在Uni学习的课程中,以与处理器启动的内存操作相关的"原子性位"的形式提出了实现锁的可能固件解决方案。

基本上,在锁定时,您会注意到您需要以原子方式执行一系列操作:测试标志的值,如果未设置,则将其设置为 locked ,否则重试。可以通过将位与 CPU 发送的每个内存请求相关联来使此序列成为原子序列。第一个 N-1 操作将设置位,而最后一个操作将取消设置位,以标记原子序列的结束。

当存储标志数据的内存模块(可以有多个模块)收到序列中第一个操作的请求(设置了其位)时,它将为它提供服务,并且不会接受来自任何其他 CPU 的请求,直到启动原子序列的 CPU 发送具有未设置原子位的请求(因为这些事务通常很短, 像这样的粗粒方法是可以接受的)。请注意,汇编程序通常通过提供"compare-and-set"类型的专用指令来简化此操作,这些指令完全符合我之前提到的操作。

最新更新