C++一种线程安全栈的设计

#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <stack>
#include <stdexcept>
#include <thread>


struct empty_stack : public std::exception {
    const char* what() const noexcept { return "Empty stack"; }
};

template <typename T> class threadsafe_stack {
private:
    std::stack<T> data;
    mutable std::mutex m;
    std::condition_variable data_condition;
    std::atomic<bool> in_waiting_state{true};

public:
    threadsafe_stack() {}
    ~threadsafe_stack() { stop(); }
    threadsafe_stack(const threadsafe_stack& other)
    {
        std::lock_guard<std::mutex> lock(m);
        data = other.data;
    }
    threadsafe_stack& operator=(const threadsafe_stack& other) = delete;

    void push(T new_value)
    {
        std::lock_guard<std::mutex> lock(m);
        data.push(std::move(new_value));
        data_condition.notify_one();
    }

    //! Updates top value in a stack.

    void update_top(T new_value)
    {
        std::lock_guard<std::mutex> lock(m);
        if (!data.empty())
            data.pop();
        data.push(std::move(new_value));
        data_condition.notify_one();
    }

    void wait_and_pop(T& value)
    {
        std::unique_lock<std::mutex> lock(m);
        data_condition.wait(lock, [this] { return !data.empty() || !in_waiting_state; });
        if (data.empty())
            throw empty_stack();
        value = std::move(data.top());
        data.pop();
    }

    std::shared_ptr<T> wait_and_pop()
    {
        std::unique_lock<std::mutex> lock(m);
        data_condition.wait(lock, [this] { return !data.empty() || !in_waiting_state; });
        if (data.empty())
            throw empty_stack();
        std::shared_ptr<T> const res(std::make_shared<T>(std::move(data.top())));
        data.pop();
        return res;
    }

    bool try_pop(T& value)
    {
        std::lock_guard<std::mutex> lock(m);
        if (data.empty())
            return false;
        value = std::move(data.top());
        data.pop();
        return true;
    }

    std::shared_ptr<T> try_pop()
    {
        std::lock_guard<std::mutex> lock(m);
        if (data.empty())
            return std::shared_ptr<T>();
        std::shared_ptr<T> res(std::make_shared<T>(std::move(data.top())));
        data.pop();
        return res;
    }

    bool empty() const
    {
        std::lock_guard<std::mutex> lock(m);
        return data.empty();
    }

    //! Terminates waiting in wait_and_pop methods.

    void stop()
    {
        std::lock_guard<std::mutex> lock(m);
        in_waiting_state = false;
        data_condition.notify_all();
    }
};

这段代码定义了一个线程安全的栈(threadsafe_stack)类模板,其中包含了多个线程安全的操作。让我们来解释一下这个类的主要功能和每个成员函数的作用:

  • std::stack<T> data:存储栈元素的私有成员变量。
  • std::mutex m:用于保护对栈数据的访问的互斥量。
  • std::condition_variable data_condition:用于线程间的同步。
  • std::atomic<bool> in_waiting_state{true}:原子布尔值,用于控制等待状态。

成员函数:

  • push(T new_value):将一个新元素压入栈顶。
  • update_top(T new_value):更新栈顶元素的值。
  • wait_and_pop(T& value):等待并弹出栈顶元素,并将其赋值给 value。
  • std::shared_ptr<T> wait_and_pop():等待并弹出栈顶元素,并返回其指针。
  • try_pop(T& value):尝试弹出栈顶元素,如果成功则将其赋值给 value。
  • std::shared_ptr<T> try_pop():尝试弹出栈顶元素,并返回其指针。
  • empty() const:检查栈是否为空。
  • stop():终止等待状态,通知所有在等待的线程。

这个线程安全的栈类实现了基本的栈操作,并确保在多线程环境下的安全性。通过使用互斥量和条件变量,它可以确保线程安全地对栈进行操作,避免了多线程环境下可能出现的竞态条件和数据竞争问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值