Skip to main content

acquire release 实现内存一致性

  1. 在单线程场景中,CPU 通常会保证程序顺序(Program Order) 的可见性,即单线程内的指令会按照代码编写的顺序执行(或看起来像是按顺序执行)存储器读写的结果也会符合单线程的预期
    1. 即使CPU有乱序功能,也会通过scoreboard等方式来处理data hazard,address hazard等,确保单线程内的内存访问都是保续的。即使现代的CPU都是超标量处理器。
  2. 但在多线程或多处理器(multi-hart)场景中,要实现多线程同时正确的对一个内存操作就会遇到问题
    1. 乱序执行(Out-of-Order Execution)
    2. 缓存分层(Cache Hierarchy),
    3. 存储缓冲区(Store Buffer)CPU有各级的存储器cache,in-flight指令暂存器
    4. 其他线程观察到的实际操作顺序与当前线程的程序顺序不一定一致
    5. 希望实现一个功能,利用一片多核都可以访问到的存储器来实现同步,这个存储器实现“锁”功能
      1. 处理器1,通过读“锁”,确定没人用,写“锁”,确保占用,不被别人使用
      2. 在处理器,读-写中间,处理器2可能就会写“锁”,从而造成错误
      3. 处理器1,准备通过写“锁”,来释放占用。但是写操作可能被乱序到当前线程的前面去执行,从而达不到保护的目的。
    6. 所以希望实现“原子指令”,实现获取“锁”,和释放“锁”的中间不会被其他的线程干扰,产生错误。
  3. 在多线程间建立 “同步关系”,通过限制 CPU 的重排序和缓存行为,确保
    1. 使用acquirereleasey语义,确保单线程内,和 LR.W 和 SC.W 指令之间是保序的。单线程内的指令实际执行顺序能被LR.W 和 SC.W控制,不收缓存和乱序的影响。
    2. 然后通过 LR.W 和 SC.W 指令,通过特殊的多线程都唯一的硬件,实现多线程之间的竞争。
  4. 从而确保
    1. 一个线程的写操作结果能被另一个线程的读操作正确感知
    2. 跨线程的操作顺序符合预期(避免 “先写后读” 变成 “先读后写” 的错乱)