#include<atomic>
#include <iostream>
#include<thread>
template<typename T>
class lock_free_stack {
private:
struct node; //前向声明
struct counted_node_ptr {
int external_count;
node* ptr;
};
struct node {
std::shared_ptr<T> data;
std::atomic<int>internal_count;
counted_node_ptr next;
node(T const& data_) : data(std::make_shared<T>(data_)), internal_count(0), next() {}
};
std::atomic<counted_node_ptr> head;
void increase_head_count(counted_node_ptr& old_counter) {
counted_node_ptr new_counter;
do {
new_counter = old_counter;
++new_counter.external_count;
} while (!head.compare_exchange_strong(old_counter, new_counter
,std::memory_order_acquire,std::memory_order_relaxed));
old_counter.external_count = new_counter.external_count;
}
public:
~lock_free_stack() {
while (pop());
}
void push(T const& data) {
counted_node_ptr new_node;
new_node.ptr = new node(data);
new_node.external_count = 1;
new_node.ptr->next = head.load(std::memory_order_relaxed);
while (!head.compare_exchange_weak(new_node.ptr->next, new_node
,std::memory_order_release,std::memory_order_relaxed));
}
std::shared_ptr<T>pop() {
counted_node_ptr old_head = head.load(std::memory_order_relaxed);
while (1) {
increase_head_count(old_head);
node* const ptr = old_head.ptr;
if (!ptr) return nullptr;
if (head.compare_exchange_strong(old_head, ptr->next,std::memory_order_relaxed)) {
std::shared_ptr<T> res;
res.swap(ptr->data);
int const count_increase = old_head.external_count - 2;
if (ptr->internal_count.fetch_add(count_increase,std::memory_order_release) == -count_increase) {
delete ptr;
}
return res;
}
else if (ptr->internal_count.fetch_sub(1,std::memory_order_relaxed) == 1) {
auto tmp = ptr->internal_count.load(std::memory_order_acquire);
delete ptr;
}
}
}
};
lock_free_stack<int >stk;
std::atomic_int tot = 1;
void push_stack() {
for (int i = 1; i <= 1000; ++i) {
std::cout << "插入数据:" << i << "\n";
stk.push(i);
}
}
void pop_stack() {
while (tot <= 1000) {
auto x = stk.pop();
if (x == nullptr) continue;
std::cout << "第" << tot++ << "次弹出数据:" << *x << "\n";
}
}
int main() {
std::thread t1(push_stack);
std::thread t2(pop_stack);
std::thread t3(pop_stack);
t1.join(); t2.join(); t3.join();
}
将内存模型运用于无锁栈
于 2024-08-26 22:35:40 首次发布