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对象时,线程安全容器可以正确地保证数据的一致性和安全性。

阅读剩余 67%

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

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

相关文章

  • Win32应用程序(SDK)设计原理详解

    Win32应用程序(SDK)设计原理详解 Win32应用程序是指运行在Windows操作系统上的应用程序。Win32应用程序的设计原理包括了应用程序的整体架构、窗口管理、消息通信、资源管理、多线程等核心技术。在本文中,我们将详细讲解Win32应用程序的设计原理及其相关技术。 应用程序的整体架构 Win32应用程序的整体架构由程序入口函数、消息循环、窗口回调函…

    C 2023年5月23日
    00
  • 基于java解析JSON的三种方式详解

    你好!下面将为你详细讲解“基于Java解析JSON的三种方式详解”的完整攻略。 什么是JSON? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由于其简洁和可读性好,目前已经成为了互联网常用的数据格式之一。 Java中解析JSON的三种方式 在Java中,解析JSON的方式主要有以下三种: 1. 通过第三方库解析…

    C 2023年5月23日
    00
  • C 程序 显示 Fibonacci 序列

    下面我来为您详细讲解如何使用C程序显示Fibonacci序列的完整攻略。 1. 什么是Fibonacci序列? Fibonacci序列是一个经典的数学问题,它的定义如下: 在斐波那契数列中,第一项和第二项都定义为1,接下来每一项都等于前面两项的和。 前十项为: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, … 2. 如何在C语言中实…

    C 2023年5月9日
    00
  • C语言程序环境中的预处理详解

    C语言程序环境中的预处理详解 什么是预处理器 在 C 语言中,预处理器是一种用于在编译程序之前处理源代码的程序,它会根据源代码中的指示来进行一系列的操作,例如文件的导入和宏的展开等。预处理器是在编译过程的第一步中被执行的,它的主要作用是生成修改了的源代码,这些修改的结果将被送入编译器进行编译和链接。 #include 指令 include 指令被用来将另一个…

    C 2023年5月23日
    00
  • C++无痛实现日期类的示例代码

    以下是实现C++日期类的完整攻略。 步骤一:设计日期类 首先,我们需要设计日期类的成员变量和成员函数。对于一个日期对象,我们通常需要记录它的年、月、日三个属性。另外,需要实现一些对日期对象的操作方法,例如: 构造函数 获取日期字符串 获取年份 获取月份 获取日 判断是否是闰年 判断是否为合法日期 因此,我们可以设计如下类: class Date { priv…

    C 2023年5月23日
    00
  • 最新C/C++中的new和delete的实现过程小结

    最新C/C++中的new和delete的实现过程小结 在C/C++语言中,动态内存的分配和释放是程序员需要频繁使用的操作,也是程序在运行时优化的一个重要部分。在最新的C/C++标准中,new和delete操作符的实现过程有一些变化和改进。这篇文章将为大家详细讲解最新C/C++中new和delete的实现过程。 new的实现过程 new是C++语言中用于动态分…

    C 2023年5月30日
    00
  • C++11智能指针unique_ptr用法使用场景分析

    C++11智能指针unique_ptr用法使用场景分析 C++11引入了智能指针的概念,对于程序员来说是一个非常方便的工具,可以帮助管理动态分配的内存,防止出现内存泄漏等问题。智能指针有三种类型:unique_ptr、shared_ptr和weak_ptr,本文主要讲解unique_ptr的用法和使用场景。 unique_ptr的定义和特点 unique_p…

    C 2023年5月23日
    00
  • C++实现PyMysql的基本功能实例详解

    C++实现PyMysql的基本功能实例详解 概述 PyMysql是一个Python编程语言下的MySQL数据库API接口,可以用来操作MySQL数据库。而本文将详细讲解如何使用C++语言实现基本的PyMysql功能。 步骤 步骤一:下载安装MySQL Connector/C++ 首先需要在本地安装MySQL Connector/C++,可以从MySQL官方网…

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