以下是经过优化后的LockFreeQueue代码:
#include
template
LockFreeQueue() : head_(new Node), tail_(head_.load()){}
~LockFreeQueue()
{
while (Node *old_head = head_.load())
{
Node *next = old_head->next_;
if (head_.compare_exchange_weak(old_head, next))
{
delete old_head;
break;
}
}
}
void push(const T &value)
{
Node *new_node = new Node(value);
Node *tail = tail_.load(std::memory_order_relaxed);
Node *next = nullptr;
while (true)
{
// 在本地栈上保存tail的下一个节点,减少对原子变量的访问
next = tail->next_.load(std::memory_order_acquire);
// 如果tail的下一个节点不存在,就将新节点附加到其后面
if (!next)
{
// 在tail的next_上使用release语义存储指针,以便其他线程可以看到这个新节点
if (tail->next_.compare_exchange_weak(next, new_node, std::memory_order_release, std::memory_order_relaxed))
{
// 如果成功插入,则退出循环
break;
}
}
else
{
// 如果tail的next_不为nullptr,说明有其他线程在进行push操作,尝试将tail指向下一个节点
tail_.compare_exchange_weak(tail, next, std::memory_order_release, std::memory_order_relaxed);
}
}
// 最后,将tail指向新节点
tail_.compare_exchange_weak(tail, new_node, std::memory_order_release);
size_.fetch_add(1, std::memory_order_release);
}
// 优化try_pop方法的实现方式
bool try_pop(T &value)
{
Node *old_head = head_.load(std::memory_order_relaxed);
while (true)
{
// 在本地栈上保存head和head的下一个节点,减少对原子变量的访问
Node *new_head = old_head->next_.load(std::memory_order_acquire);
if (!new_head)
{
// 如果head的下一个节点不存在,则队列为空,退出循环
return false;
}
// 使用CAS操作将head指向下一个节点,如果成功,则可以删除旧的head节点
if (head_.compare_exchange_weak(old_head, new_head, std::memory_order_release, std::memory_order_relaxed))
{
value = new_head->value_;
size_.fetch_sub(1, std::memory_order_release);
delete old_head;
return true;
}
// 如果CAS操作失败,则有其他线程正在进行pop操作,需要重新读取head的值
old_head = head_.load(std::memory_order_relaxed);
}
}
bool empty() const
{
return size_.load(std::memory_order_acquire) == 0;
}
private:
struct Node
{
T value_;
std::atomic<Node *> next_;
Node() : value_(T()), next_(nullptr) {}
explicit Node(const T &value) : value_(value), next_(nullptr) {}
};
std::atomic<Node *> head_;
std::atomic<Node *> tail_;
std::atomic<size_t> size_{0};
};