标题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技术站