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

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>对其加锁。

运行上述程序,可以看到,在多个线程同时操作同一个std::stack对象时,线程安全容器可以正确地保证数据的一致性和安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++线程安全容器stack和queue的使用详细介绍 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C语言实现医院管理系统

    C语言实现医院管理系统攻略 1. 确定功能需求 在开始编写医院管理系统之前,需要先明确需要实现的功能需求。医院管理系统可能包括以下功能: 患者基本信息管理(包括姓名、年龄、性别等信息) 患者就诊记录管理(包括挂号时间、就诊科室、医生名称、费用等信息) 医生基本信息管理(包括姓名、性别、年龄、职称等信息) 医生排班信息管理(包括医生姓名、科室、上班时间等信息)…

    C 2023年5月23日
    00
  • C++实现红黑树应用实例代码

    C++实现红黑树应用实例代码 什么是红黑树 红黑树(Red-Black Tree)是一种自平衡二叉查找树,在C++中的STL中的set和map就是基于红黑树实现的。红黑树满足以下性质: 每个节点或者是黑色,或者是红色。 根节点是黑色。 每个叶子节点(NIL节点,空节点)是黑色的。 如果一个节点是红色的,则它的两个子节点都是黑色的。 对于任意一个节点而言,其到…

    C 2023年5月24日
    00
  • C语言入门篇–初识C语言及数据类型

    C语言入门篇–初识C语言及数据类型 一、C语言概述 C语言是一种高级编程语言,它可以编写底层的系统软件和高级的应用程序。它在计算机领域中的优势在于它快速、高效、稳定,且是一种跨平台的语言。 二、数据类型 在C语言中,数据类型用于定义不同类型的变量。C语言提供了许多内置的数据类型,例如int、float、char等等。 1.整数型(int) 整数型是最基本的…

    C 2023年5月23日
    00
  • C++实现简单的学生管理系统

    C++实现学生管理系统攻略 1. 确定系统功能 学生管理系统有很多功能,有录入学生信息、显示学生信息、修改学生信息、删除学生信息等。确定系统功能是实现该系统的第一步。本系统以录入、显示、修改、删除学生信息为功能点展开。 2. 设计学生类 学生信息的属性有:学号、姓名、性别、出生年月、成绩。因此,我们可以设计一个学生类 Student,并在其中定义相应的属性和…

    C 2023年5月22日
    00
  • Java读取项目json文件并转为JSON对象的操作

    读取项目中的json文件并转为JSON对象是Java编程中比较常见的操作,下面是详细的攻略。 1. 准备工作 在开始操作之前,请确保项目中已经有一个json文件,在这个文件中写入一些JSON格式的数据。 例如,我们可以创建一个名为example.json的文件,里面的内容如下: { "name": "John Doe"…

    C 2023年5月23日
    00
  • C语言返回函数指针

    C语言中可以通过函数返回指针来返回指向特定数据类型的指针。返回函数指针的语法形式为:data_type (* function_name(parameters)),其中,data_type表示待返回指针的数据类型,function_name表示函数名,parameters表示函数参数。 具体来说,C语言返回函数指针的步骤如下: 1.声明返回指针:首先需要声明…

    C 2023年5月9日
    00
  • C/C++实现HTTP协议解析的示例代码

    C/C++实现HTTP协议解析的示例代码的完整攻略如下: 一、准备工作 在开始编写HTTP协议解析代码前,需要安装以下工具:- C/C++编译器:例如gcc、Visual Studio等。- cURL库:用于发送HTTP请求和接收HTTP响应。 二、HTTP协议解析 1. TCP连接 在使用HTTP协议进行通信时,首先需要建立TCP连接。可以使用C/C++的…

    C 2023年5月24日
    00
  • C++静态库与动态库文件的生成和使用教程

    以下是关于C++静态库与动态库文件的生成和使用教程的详细攻略。 什么是C++静态库和动态库? C++库文件是编写的代码的编译结果,可以用来在其他项目中共享代码。C++库文件可以分为静态库和动态库两种。 静态库(Static Library)是指在链接过程中,将库的代码和目标程序的代码一起组合成一个可执行程序。静态库编译后的文件后缀名通常为 .a (Unix)…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部