自旋锁原理分析

Posted jiau

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自旋锁原理分析相关的知识,希望对你有一定的参考价值。

1. 概念

自旋锁的目的是在短期间内进行轻量级的锁定,解决对某项共享资源的互斥使用,在等待锁重新可用期间进行自旋,所以自旋锁不应该被持有时间过长,如果需要长时间锁定的话,推荐使用信号量。实际操作的数据结构如下:
技术图片

2. 获取锁

最终执行的代码是体系结构相关的自旋锁实现:arch_spin_lock。
技术图片

3. 代码分析

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
  unsigned long tmp;
  u32 newval;
  arch_spinlock_t lockval;
  // 处理器通知内存系统将对某个地址的内存进行读写
  prefetchw(&lock->slock);
  // 以独占的方式对 lock->tickets.next 执行 +1 操作
  __asm__ __volatile__(
"1:  ldrex  %0, [%3]
"
"  add  %1, %0, %4
"
"  strex  %2, %1, [%3]
"
"  teq  %2, #0
"
"  bne  1b"
  : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
  : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
  : "cc");
  // 判断是否轮到自己拥有自旋锁
  while (lockval.tickets.next != lockval.tickets.owner) {
    // 将当前核心挂起等待其他核心发送信号,也就是等 SEV 指令
    wfe();
    // 读取自旋锁中的 lock->tickets.owner
    lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
  }
  // 数据同步
  smp_mb();
}

4. 释放锁

最终执行的代码是体系结构相关的自旋锁实现:arch_spin_unlock。
技术图片

5. 代码分析

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
  // 数据同步
  smp_mb();
  // 将自旋锁交给下一个使用者
  lock->tickets.owner++;
  // 先进行数据同步,然后给其他核心发信号
  dsb_sev();
}

6. 总结

自旋锁底层实现依赖于体系结构相关的汇编指令,在进行自旋锁操作时,使用独占指令LDREX/STREX;在自旋时使用指令WFE将当前核心挂起,等待被唤醒;当核心在释放自旋锁时,使用SEV指令通知其他所有核心。




以上是关于自旋锁原理分析的主要内容,如果未能解决你的问题,请参考以下文章

原子类与自旋锁原理初探

自旋锁原理及java自旋锁

synchronized实现原理及其优化-(自旋锁,偏向锁,轻量锁,重量锁)

互斥锁自旋锁读写锁和条件变量

互斥锁,自旋锁,原子操作原理和实现

Synchronized的原理及自旋锁,偏向锁,轻量级锁,重量级锁的区别(摘抄和理解)