c++11 多线程编程——如何实现线程安全队列

标题1:c++11多线程编程——如何实现线程安全队列

转眼间,多线程编程已经成为了现代软件开发中必不可少的一项技能,而线程安全队列则是其中非常重要的一个思路,下面我们就来详细讲解一下如何在c++11中实现线程安全队列。

标题2:实现方法1:使用锁

使用锁是最常见、最简单的实现线程安全队列的方法。

示例1:

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

template<typename T>
class Queue {
private:
    std::queue<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable m_cv; 

public:
    void push(const T& item) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_queue.push(item);
        m_cv.notify_one();
    }

    bool pop(T& item) {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_cv.wait(lock, [this] {return !m_queue.empty(); });
        if (m_queue.empty()) {
            return false;
        }
        item = std::move(m_queue.front());
        m_queue.pop();
        return true;
    }

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

示例2:

#include <iostream>
#include <thread>

Queue<int> my_queue;

void producer() {
    for (int i = 1; i <= 10; i++) {
        my_queue.push(i);
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void consumer() {
    int item = 0;
    for (int i = 1; i <= 10; i++) {
        while (!my_queue.pop(item)) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        std::cout << "Item " << item << " is popped." << std::endl;
    }
}

int main() {
    std::thread producer_thread(producer);
    std::thread consumer_thread(consumer);
    producer_thread.join();
    consumer_thread.join();
}

思路解析:

示例1中给出了一个基本的线程安全队列实现,其中的锁和条件变量是保证线程安全的关键,push、pop和empty三个函数分别实现了队列的插入、删除和判空操作,并且在push操作中通过条件变量通知等待队列的线程。示例2则是一个简单的测试程序,通过开启一个生产者线程和一个消费者线程,验证了线程安全队列的正确性。

标题3:实现方法2:使用原子操作

相比于使用锁的方式,原子操作是一种更轻量级的实现线程安全的方法,既可以避免死锁等锁相关的问题,同时还能够提供更高的并发性。

示例1:

#include <queue>
#include <thread>
#include <atomic>
#include <chrono>

template<typename T>
class Queue {
private:
    std::queue<T> m_queue;
    std::atomic_bool m_flag;

public:
    Queue() : m_flag(false) {}

    void push(const T& item) {
        m_queue.push(item);
        m_flag.store(true, std::memory_order_release);
    }

    bool pop(T& item) {
        if (m_flag.load(std::memory_order_acquire)) {
            if (!m_queue.empty()) {
                item = std::move(m_queue.front());
                m_queue.pop();
                return true;
            }
            else {
                m_flag.store(false, std::memory_order_release);
            }
        }
        return false;
    }

    bool empty() const {
        return m_queue.empty();
    }
};

示例2:

#include <iostream>
#include <thread>

Queue<int> my_queue;

void producer() {
    for (int i = 1; i <= 10; i++) {
        my_queue.push(i);
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void consumer() {
    int item = 0;
    for (int i = 1; i <= 10; i++) {
        while (!my_queue.pop(item)) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        std::cout << "Item " << item << " is popped." << std::endl;
    }
}

int main() {
    std::thread producer_thread(producer);
    std::thread consumer_thread(consumer);
    producer_thread.join();
    consumer_thread.join();
}

思路解析:

示例1中实现的线程安全队列使用了std::atomic_bool类型的m_flag,同时还使用了memory_order_release和memory_order_acquire等原子操作来保证线程安全,其中前者用于push操作,后者用于pop操作,同时在pop中还对队列为空的情况进行了判断,并且在队列变为空时,将m_flag重置为false,以通知未来的push操作继续往队列中插入元素。示例2同样是对线程安全队列的基本测试程序。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++11 多线程编程——如何实现线程安全队列 - Python技术站

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

相关文章

  • Java并发编程之volatile与JMM多线程内存模型

    Java并发编程之volatile与JMM多线程内存模型 什么是多线程内存模型 多线程内存模型是描述多个线程执行程序时,各自对内存读写操作的行为规定。Java中的多线程内存模型简称JMM。JMM描述了Java虚拟机(JVM)在运行多线程程序时,线程之间如何进行通信、数据之间如何同步等问题。它规定了一个线程在什么情况下可以看到另一个线程对共享变量所做的修改。 …

    多线程 2023年5月17日
    00
  • Go并发与锁的两种方式该如何提效详解

    Go并发与锁的两种方式该如何提效详解 先谈一下Go中的协程和锁 Go语言的协程是一种并发执行代码的方式。协程可以方便的并发执行任务,不需要等待前面的任务完成,直接执行下一个任务,提高了程序运行的效率。 而锁则可以保证在多个协程同时访问共享数据时不会发生冲突。 对于共享数据的并发访问,常用的两种方式 1. 互斥锁 互斥锁是最常用的一种锁。它可以保证在同一时刻只…

    多线程 2023年5月16日
    00
  • C++中std::thread线程用法

    下面是详细讲解C++中std::thread线程用法的攻略。 C++中std::thread线程用法攻略 简述 C++11引入了std::thread库,使得多线程编程变得更加容易和便捷。 std::thread库提供了一种方便的方式来创建和控制线程,支持并发执行多个任务,在多核处理器上能够发挥出更好的性能。 在本攻略中,我们将详细讲解C++中std::th…

    多线程 2023年5月17日
    00
  • 详解Java创建多线程的四种方式以及优缺点

    详解Java创建多线程的四种方式以及优缺点 在Java中,实现多线程的方式有以下四种: 继承Thread类 实现Runnable接口 实现Callable接口 使用线程池 下面将详细介绍每种方式的优缺点,并提供示例。 1. 继承Thread类 继承Thread类是一种最简单的创建线程的方法。代码示例如下: public class MyThread exte…

    多线程 2023年5月17日
    00
  • Nodejs高并发原理示例详解

    接下来我将详细讲解“Node.js高并发原理示例详解”的完整攻略。 Node.js高并发原理示例详解 什么是Node.js Node.js 是一个开源、跨平台的 JavaScript 运行环境,它允许我们使用 JavaScript 来编写后端服务器应用程序。它是建立在 Chrome V8 引擎的基础之上,利用它提供的非阻塞 I/O 和事件驱动模型,在处理大量…

    多线程 2023年5月17日
    00
  • Apache ab并发负载压力测试实现方法

    一、Apache ab并发负载压力测试的背景 Apache ab是一个命令行工具,它可以用来进行HTTP/HTTPS等协议的并发负载压力测试。在进行网站或者应用程序的性能测试时,经常需要使用这个工具。 二、安装Apache ab 在大多数Linux操作系统上,Apache ab都已经包含在Apache web服务器软件包中。如果没有安装Apache软件包,可…

    多线程 2023年5月16日
    00
  • C++多线程传参的实现方法

    以下是详细讲解C++多线程传参的实现方法的完整攻略。 什么是C++多线程传参 在C++中,多线程编程是通过创建多个线程来同时执行不同的任务或者处理不同的数据的。多线程编程中,线程之间需要相互传递数据、参数或者消息等,才能共同协作完成任务。 因此,在C++中,如何实现多线程之间的数据传递就显得尤为重要。 C++多线程传参的实现方法 1. 通过全局变量传参 全局…

    多线程 2023年5月17日
    00
  • 深入理解JS中的Promise.race控制并发量

    标题:深入理解JS中的Promise.race控制并发量 简介 JavaScript中的Promise是一种处理异步操作的方式,而Promise.race方法则是Promise对象上的一种方法,它与其他方法不同的是,只要其中的一个Promise状态被改变,Promise.race的状态就会被改变。这个方法通常用来控制异步操作的并发数,即同时进行的异步操作数量…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部