【问题标题】:How locking is implemented?锁定是如何实现的?
【发布时间】:2012-08-14 11:12:06
【问题描述】:

我有以下代码:

 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

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

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

【问题讨论】:

  • 哪个算法,你有这个代码???
  • "读取或更改锁定值本身就是一条多指令" - 并非总是如此。原子操作由多种架构提供。锁定实现会使用这些,具体取决于硬件。
  • 该操作(指令)的原子性是如何实现的?
  • 它是 impl。通过硬件,如果您真的想了解更多信息,可以查找 MESI 协议之类的东西(尽管它并不暗示原子操作本身)。 @David 的回答足以让您入门,

标签: multithreading locks


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 感谢您的回复。但真正让我兴奋的是你最后的cmets。您能否详细解释一下您的“2)”,或者提供一些很好的参考资料来理解它的功能。?
  • 它是特定于平台的。对于 x86,请参阅 cmpxchgpause a.k.a rep nop。在 x86 上,不需要内存屏障,但通常需要编译器优化屏障 (memory clobber)。不幸的是,它很快就会变得非常复杂。
【解决方案2】:

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

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

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

【讨论】:

  • 请注意,这不是我所知道的任何现代计算机系统上实现锁定的方式。这是一个理解它的模型,因为现代系统表现得“好像”他们这样做了。这种方法的主要问题是它会减慢锁定内存速度,而在现代计算机上,内存太慢而无法用于此目的。 (这就是我们拥有所有这些缓存的原因——内存比 CPU 慢。)
  • @David Schwartz:确实,它看起来确实像“学术”的做事方法。我想这只是展示这个过程中涉及到什么样的机制才有用。
  • @David 请解释“现代系统表现得好像他们这样做了”?
  • 虽然他们实际上并没有这样做,但他们看起来好像他们这样做了。例如,它们不是锁定内存总线,而是将一块内存锁定到缓存中。它在该位内存上的操作原子性方面实现了相同的效果,但不会干扰对内存其他部分的访问。
猜你喜欢
  • 2016-10-15
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多