1

我有以下代码:

 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

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

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

4

2 回答 2

2

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

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

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

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

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

例如,SMP Pentium Pro 系统有一个错误,需要在解锁操作中进行特殊处理。锁定算法的幼稚实现将导致分支预测逻辑期望操作继续旋转,从而在最坏的可能时间(当您第一次获取锁定时)导致巨大的性能损失。锁定算法的简单实现可能会导致两个内核各自等待同一个锁定使总线饱和,从而减慢需要完成工作以释放锁定的 CPU。这些都需要大量的魔法和对要处理的硬件的深刻理解。

于 2012-08-14T11:23:15.287 回答
0

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

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

当存储标志数据的内存模块(可以有多个模块)接收到序列中第一个操作的请求(其位被设置)时,它将为它服务并且不会接受来自任何其他CPU的请求,直到CPU启动原子序列发送带有未设置原子性位的请求(因为这些事务通常很短,因此可以接受这样的粗粒度方法)。请注意,汇编器提供的“比较和设置”类型的专门指令通常会使这变得更容易,这些指令与我之前提到的完全一样。

于 2012-08-14T12:37:54.537 回答