利用std::atomic实现无锁队列

队列基础,一对一无锁

队列就是一个先进先出的数据结构,一般使用链表实现,如下图:

数据从Head进入链表,从Tail出链表。我们会发现,只要链表一直不是空的,那么Head指针和Tail指针是完全无关的,也就是读写之间不加锁的线程安全比较容易实现,我们只要保证链表从初始化开始Head和Tail就无关即可,那么一对一的生产者和消费者无锁队列就可以十分简单地实现,显然Tail或者Head直接指向的内存我们不用来存储数据,是最合理的。

上述两种方式都可以,我们采用第一种展开讲述。在队列创建时,我们让Head和Tail共同指向一个不存储数据的内存,从此这两个指针就可以毫不相干了,后续生产消费中,Tail总是预留一个不存储数据的内存节点,而Head则只需要完成自己的指向操作。以下是相关代码:

template <typename T>
class T1V1Queue : NonCopyable {
 public:
  using ElementType = T;
  T1V1Queue() : mSize(0) { mHead = mTail = new TNode; }
  ~T1V1Queue() {
    while (mTail != nullptr) {
      T
### 互斥机制的实现基础 在多线程编程中,互斥机制用于确保多个线程不会同时访问共享资源,从而避免数据竞争和不一致的状态。`std::atomic` 是 C++11 引入的标准库工具,它提供了一种轻量级的、基于硬件支持的原子操作机制,可以用来实现线程间的同步和互斥访问共享数据。 `std::atomic` 的核心在于它对特定类型的操作提供了原子性保证。这意味着,即使在多个线程并发执行的情况下,这些操作也不会被中断或部分执行,从而避免了中间状态的暴露。例如: ```cpp std::atomic<bool> flag(false); // 线程 A flag.store(true, std::memory_order_seq_cst); // 线程 B if (flag.load(std::memory_order_seq_cst)) { // 安全地访问共享资源 } ``` 上述代码中,`store` 和 `load` 操作是原子的,并且通过 `std::memory_order_seq_cst`(顺序一致性)内存序保证了操作的可见性和顺序性。这种机制可以用来构建简单的互斥锁,如自旋锁(spinlock)或信号量。 ### 内存序与同步语义 `std::atomic` 的互斥实现不仅依赖于原子性,还依赖于内存序(memory order)的约束。内存序决定了操作对其他线程的可见顺序。常见的内存序包括: - `std::memory_order_relaxed`:仅保证操作的原子性,不提供任何同步语义。 - `std::memory_order_acquire` 和 `std::memory_order_release`:用于构建同步屏障,确保操作前后的内存访问顺序。 - `std::memory_order_seq_cst`:最强的内存序,确保所有线程看到的操作顺序一致。 例如,在实现一个简单的互斥锁时,可以使用 `std::atomic_flag` 或 `std::atomic<bool>` 来表示锁的状态,并通过 `test_and_set` 或 `exchange` 操作实现原子的加锁和解锁: ```cpp class SpinLock { public: void lock() { while (flag.test_and_set(std::memory_order_acquire)) { // 等待锁释放 } } void unlock() { flag.clear(std::memory_order_release); } private: std::atomic_flag flag = ATOMIC_FLAG_INIT; }; ``` 在此示例中,`test_and_set` 是一个原子操作,它将标志设置为 `true` 并返回其先前的值。如果标志已经被设置,则线程会持续等待,直到其他线程调用 `unlock` 并清除标志。 ### 原子操作与内存屏障 除了提供原子性,`std::atomic` 还可以通过显式的内存屏障(fence)来控制内存访问顺序。例如,`std::atomic_thread_fence` 可以插入一个屏障,防止编译器和处理器对内存操作进行重排序[^1]。这在实现更复杂的同步结构(如无锁队列)时非常有用。 ```cpp std::atomic<int> x(0), y(0); int r1, r2; void thread1() { x.store(1, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_release); r1 = y.load(std::memory_order_relaxed); } void thread2() { y.store(1, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_release); r2 = x.load(std::memory_order_relaxed); } ``` 在上述代码中,`std::atomic_thread_fence` 用于确保 `store` 操作在 `load` 操作之前执行,从而避免因重排序导致的错误结果。 ### 总结 `std::atomic` 提供了一种高效、灵活的方式来实现线程间的互斥和同步。它通过原子操作和内存序控制,确保对共享数据的访问是线程安全的。相比于传统的互斥锁(如 `std::mutex`),`std::atomic` 具有更低的开销,适用于对性能要求较高的场景,但也需要开发者对内存模型有更深入的理解。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值