这会是c中的一个正常工作的自旋锁吗?

Posted

技术标签:

【中文标题】这会是c中的一个正常工作的自旋锁吗?【英文标题】:would this be a functioning spinlock in c? 【发布时间】:2021-09-24 01:44:50 【问题描述】:

我目前正在学习操作系统,并且想知道使用这些定义,这会按预期工作还是我错过了一些原子操作?

int locked = 0;

void lsLock()
  while(1) 
    if (locked)
      continue;
     else 
      locked = 1;
      break;
    
   


void lsUnlock()
  locked = 0;

提前致谢!

【问题讨论】:

没有。自旋锁实现需要非标准的锁定指令。您需要使用特定于编译器的代码来实现它。你可以先看这里***.com/questions/1383363/… 想象两个线程运行lsLock 函数,它们都以locked == 0 开始执行——它们都检查if (locked)——它们都看到它为零——它们都锁定它。 @4386427 我忘记了 else 块中的中断。但即使有了它,它也行不通,对吧? @Flowmotion 不,它不会工作。有几个原因。 【参考方案1】:

第一个问题是编译器假定任何“外部”都不会改变任何东西(除非它被标记为volatile);这意味着编译器能够对此进行优化:

int locked = 0;

void lsLock()
  while(1) 
    if (locked)
      continue;
     else 
      locked = 1;
      break;
    
   

..进入这个:

int locked = 0;

void lsLock()
  if (locked)
    while(1)  
  
  locked = 1;

显然,如果有其他东西修改 locked,这将不起作用 - 一旦 while(1) 启动它就不会停止。要解决这个问题,您可以使用volatile int locked = 0;

这只防止编译器假设locked 没有改变。没有什么能阻止理论上的 CPU 玩类似的把戏(例如,即使使用 volatile,非缓存一致的 CPU 也无法实现不同的 CPU 更改 locked)。为了保证,您需要使用原子或其他东西(例如内存屏障)。

但是;使用volatile int locked 可能会起作用,尤其是对于常见的 80x86 CPU。请注意,“工作”可以被认为是最坏的可能性 - 它导致假设代码很好,然后当您为不同的 CPU 编译相同的代码时会出现壮观的(并且由于时间问题几乎无法调试)灾难。

【讨论】:

以上是关于这会是c中的一个正常工作的自旋锁吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的自旋锁,手动实现一个自旋锁

Java中的自旋锁,手动实现一个自旋锁

linux驱动程序中的并发控制-3(读写自旋锁)-45

linux驱动程序中的并发控制-3(读写自旋锁)-45

JVM锁优化

自旋锁