C++线程安全容器stack和queue的使用详细介绍

本文详细介绍了C++线程安全容器stack和queue的使用。线程安全容器可支持多线程并发访问,避免并发环境下非线程安全容器出现的数据竞争、死锁等问题。文中介绍了std::stack的特性,并给出两个使用示例,同时指出使用时需加互斥锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

C++线程安全容器stack和queue的使用详细介绍

什么是线程安全容器

为什么需要线程安全容器

C++线程安全容器

std::stack

示例1

示例2


C++线程安全容器stack和queue的使用详细介绍

什么是线程安全容器

线程安全容器是可以支持在多个线程并发访问的STL容器。在多线程程序中使用线程安全容器可以保证数据操作的正确性和安全性。

为什么需要线程安全容器

在并发环境中,多个线程可能同时访问同一资源。对于非线程安全的容器,在多线程的情况下容易出现数据竞争、死锁等问题。线程安全容器可以避免这种问题的发生,保证程序的正确性。

C++线程安全容器

C++ STL库提供了一些线程安全容器,包括std::stackstd::queue,它们都是基于顺序容器实现的。这些容器提供了多个线程的并发访问功能。

std::stack

std::stack是一个后进先出(LIFO)的容器。将元素插入std::stack中时,总是插入到栈顶(最近插入的元素为栈顶元素),删除元素时,总是从栈顶弹出。

示例1

下面是一个使用std::stack的简单示例程序:

#include <iostream>
#include <stack>
#include <thread>

void foo(std::stack<int>& s) {
    for (int i=0; i<5; ++i) {
        s.push(i);
        std::cout << "push: " << i << std::endl;
    }
}

void bar(std::stack<int>& s) {
    while (!s.empty()) {
        std::cout << "pop: " << s.top() << std::endl;
        s.pop();
    }
}

int main() {
    std::stack<int> s;
    std::thread t1(foo, std::ref(s));
    std::thread t2(bar, std::ref(s));
    t1.join();
    t2.join();
    return 0;
}

上述程序中,我们创建了一个std::stack对象s,然后创建了两个线程t1t2,分别调用foobar函数。在foo函数中,我们向s中插入5个元素;在bar函数中,我们从s中不断取出元素,直到栈为空。注意,我们在调用foobar函数时,要将s对象传递给它们作为参数。

运行上述程序,可以看到,两个线程正确地对同一个std::stack对象进行了并发访问,没有发生任何错误。

示例2

下面是另一个std::stack的示例程序,演示了如何在多个线程中同时对栈进行修改操作:

#include <iostream>
#include <stack>
#include <thread>

template<typename T>
void safe_push(std::stack<T>& s, T val) {
    std::lock_guard<std::mutex> lock(s.mtx);
    s.stk.push(val);
}

template<typename T>
T safe_pop(std::stack<T>& s) {
    std::lock_guard<std::mutex> lock(s.mtx);
    if (s.stk.empty()) {
        return T();
    }
    T val = s.stk.top();
    s.stk.pop();
    return val;
}

template<typename T>
size_t safe_size(std::stack<T>& s) {
    std::lock_guard<std::mutex> lock(s.mtx);
    return s.stk.size();
}

template<typename T>
bool safe_empty(std::stack<T>& s) {
    std::lock_guard<std::mutex> lock(s.mtx);
    return s.stk.empty();
}

template<typename T>
void print_stack(std::stack<T>& s) {
    std::lock_guard<std::mutex> lock(s.mtx);
    while (!s.stk.empty()) {
        std::cout << s.stk.top() << " ";
        s.stk.pop();
    }
    std::cout << std::endl;
}

struct Stack {
    std::mutex mtx;
    std::stack<int> stk;
};

void foo(Stack& s) {
    for (int i=0; i<10; ++i) {
        safe_push(s.stk, i*10);
        std::cout << "push: " << i*10 << std::endl;
    }
}

void bar(Stack& s) {
    for (int i=0; i<5; ++i) {
        std::cout << "pop: " << safe_pop(s.stk) << std::endl;
    }
}

int main() {
    Stack s;
    std::thread t1(foo, std::ref(s));
    std::thread t2(bar, std::ref(s));
    t1.join();
    t2.join();
    std::cout << "size: " << safe_size(s.stk) << std::endl;
    if (safe_empty(s.stk)) {
        std::cout << "stack is empty" << std::endl;
    }
    return 0;
}

上述程序中,我们定义了一个Stack结构体,其中包含了一个std::mutex对象和一个std::stack对象。我们通过定义一些线程安全的操作(比如safe_pushsafe_pop等)来对std::stack进行访问。在foo函数中,我们插入了10个元素;在bar函数中,我们弹出了一些元素。注意,我们在对std::stack进行修改时,必须使用std::lock_guard<std::mutex>对其加锁。

Note: 这里虽然说是安全容器,但是使用时还是需要自己添加互斥锁来保护,并不是真正的可以直接使用的安全容器。

请注明出处:C++线程安全容器stack和queue的使用详细介绍 - Python技术站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值