跳转至

wait-free编程

  • 定义:每线程有限步完成,调度/挂起不影响;强于 lock-free,杜绝饥饿和无界自旋。
  • 核心机制:Helping 协作,线程遇到未完成操作时主动帮忙完成,避免重试循环。
  • 状态编码:高位放标志位(如 is_zero、helped),一次原子读写携带数据+状态。
  • 线性一致性:用逻辑顺序解释交错,当 CAS 失败因他人修改时直接判定顺序并返回,无需自旋。
  • 适用:读多写少、对 P99/P999 极敏感或不可阻塞的底层场景(引用计数、低延迟渠道)。
  • 取舍:更多原子/状态判断,代码复杂;写密集或对尾延迟不敏感时,lock-free/自旋锁可能更优。

Wait-Free Sticky Counter 示例

#include <atomic>
#include <cstdint>

struct WaitFreeCounter {
  static constexpr uint64_t is_zero = 1ull << 63;
  static constexpr uint64_t helped = 1ull << 62;
  std::atomic<uint64_t> counter{1};  // 低 62 位为计数

  uint64_t read() {
    uint64_t val = counter.load(std::memory_order_acquire);
    if (val == 0 && counter.compare_exchange_strong(
                        val, is_zero | helped, std::memory_order_acq_rel)) {
      return 0;  // 帮忙固化零
    }
    return (val & is_zero) ? 0 : (val & ~(is_zero | helped));
  }

  bool decrement() {
    if (counter.fetch_sub(1, std::memory_order_acq_rel) == 1) {
      uint64_t expect = 0;
      if (counter.compare_exchange_strong(expect, is_zero,
                                          std::memory_order_acq_rel)) {
        return true;  // 自己固化零
      } else if ((expect & helped) &&
                 (counter.exchange(is_zero, std::memory_order_acq_rel) &
                  helped)) {
        return true;  // 已被协助固化
      }
    }
    return false;  // 未归零或逻辑顺序上被加回
  }

  bool increment_if_not_zero() {
    return (counter.fetch_add(1, std::memory_order_acq_rel) & is_zero) == 0;
  }
};

提示:用高位偷位携带状态,读操作也参与协助;无循环,自旋抖动被消除。