1. 程式人生 > >C++11:基於std::queue和std::mutex構建一個執行緒安全的佇列

C++11:基於std::queue和std::mutex構建一個執行緒安全的佇列

C++中的模板std::queue提供了一個佇列容器,但這個容器並不是執行緒安全的,如果在多執行緒環境下使用佇列,它是不能直接拿來用的。
基於它做一個執行緒安全的佇列也並不複雜。基本的原理就是用std::mutext訊號量對std::queue進行訪問控制,以保證任何一個執行緒都是獨佔式訪問,下面是完整的程式碼。

/*
 * threadsafe_queue.h
 *
 *  Created on: 2016年7月26日
 *      Author: guyadong
 */

#ifndef COMMON_SOURCE_CPP_THREADSAFE_QUEUE_H_
#define COMMON_SOURCE_CPP_THREADSAFE_QUEUE_H_
#include <queue> #include <mutex> #include <condition_variable> #include <initializer_list> namespace gdface { inline namespace mt{ /* * 執行緒安全佇列 * T為佇列元素型別 * 因為有std::mutex和std::condition_variable類成員,所以此類不支援複製建構函式也不支援賦值操作符(=) * */ template<typename T> class threadsafe_queue{ private
: // data_queue訪問訊號量 mutable std::mutex mut; mutable std::condition_variable data_cond; using queue_type = std::queue<T>; queue_type data_queue; public: using value_type= typename queue_type::value_type; using container_type = typename queue_type::container_type; threadsafe_queue()=default
; threadsafe_queue(const threadsafe_queue&)=delete; threadsafe_queue& operator=(const threadsafe_queue&)=delete; /* * 使用迭代器為引數的建構函式,適用所有容器物件 * */ template<typename _InputIterator> threadsafe_queue(_InputIterator first, _InputIterator last){ for(auto itor=first;itor!=last;++itor){ data_queue.push(*itor); } } explicit threadsafe_queue(const container_type &c):data_queue(c){} /* * 使用初始化列表為引數的建構函式 * */ threadsafe_queue(std::initializer_list<value_type> list):threadsafe_queue(list.begin(),list.end()){ } /* * 將元素加入佇列 * */ void push(const value_type &new_value){ std::lock_guard<std::mutex>lk(mut); data_queue.push(std::move(new_value)); data_cond.notify_one(); } /* * 從佇列中彈出一個元素,如果佇列為空就阻塞 * */ value_type wait_and_pop(){ std::unique_lock<std::mutex>lk(mut); data_cond.wait(lk,[this]{return !this->data_queue.empty();}); auto value=std::move(data_queue.front()); data_queue.pop(); return value; } /* * 從佇列中彈出一個元素,如果佇列為空返回false * */ bool try_pop(value_type& value){ std::lock_guard<std::mutex>lk(mut); if(data_queue.empty()) return false; value=std::move(data_queue.front()); data_queue.pop(); return true; } /* * 返回佇列是否為空 * */ auto empty() const->decltype(data_queue.empty()) { std::lock_guard<std::mutex>lk(mut); return data_queue.empty(); } /* * 返回佇列中元素數個 * */ auto size() const->decltype(data_queue.size()){ std::lock_guard<std::mutex>lk(mut); return data_queue.size(); } }; /* threadsafe_queue */ }/* namespace mt */ }/* namespace gdface */ #endif /* COMMON_SOURCE_CPP_THREADSAFE_QUEUE_H_ */

這裡只實現了阻塞式的pop函式wait_and_pop,你也可以根據自己的需要對程式碼進行適當的改造,以符合自己的需求。
(C++11風格程式碼,在VS2015和gcc5.2.0下編譯通過)

相關推薦

C++11:基於std::queuestd::mutex構建一個執行安全佇列

C++中的模板std::queue提供了一個佇列容器,但這個容器並不是執行緒安全的,如果在多執行緒環境下使用佇列,它是不能直接拿來用的。 基於它做一個執行緒安全的佇列也並不複雜。基本的原理就是用std::mutext訊號量對std::queue進行訪問控制,以

C++11執行安全佇列安全

文章程式碼取自C++11併發程式設計指南,記錄於此方便日後檢視 #include "stdafx.h" #include <thread> #include <iostream> #include <vector> #include &l

c++11寫的一個執行安全佇列

#ifndef __MSG__QUEUE__H__ #define __MSG__QUEUE__H__ #include <thread> #include <mutex>

C++11執行安全佇列

多執行緒程式設計需要實現一個執行緒安全的佇列,上鎖,避免多個執行緒同時讀寫 程式碼: /** * 執行緒安全的佇列 */ #ifndef __THREAD_SAFE_QUEUE__ #def

c++11 新特性實戰 (一):多執行操作

# c++11 新特性實戰 (一) ## c++11多執行緒操作 * 執行緒 * **thread** ```c++ int main() { thread t1(Test1); t1.join(); thread t2(Test2);

Spring bean 單例bean的執行安全

Bean的作用域    Spring 3中為Bean定義了5中作用域,分別為singleton(單例)、prototype(原型)、request、session和global session,5種作用域說明如下: singleton:單例模式,Spring I

C++設計一個執行安全的懶漢單例模式

#incldue<iostream> #include<mutex> using namespace std; class CSingleton { public: static CSingleton* GetCSingleton() { if (_p ==

5個步驟,教你瞬間明白執行中原六仔出售執行安全

記得中原六仔出售 dsluntan.com Q:3393756370 VX:17061863513今年3月份剛來杭州面試的時候,有一家公司的技術總監問了我這樣一個問題:你來說說有哪些執行緒安全的類?我心裡一想,這我早都背好了,稀里嘩啦說了一大堆。 他又接著問:

執行安全佇列Queue

使用非阻塞佇列的時候有一個很大問題就是:它不會對當前執行緒產生阻塞,那麼在面對類似消費者-生產者的模型時,就必須額外地實現同步策略以及執行緒間喚醒策略,這個實現起來就非常麻煩。但是有了阻塞佇列就不一樣了,它會對當前執行緒產生阻塞,比如一個執行緒從一個空的阻塞佇列中取元素,此時執行緒會被阻塞直到阻塞佇

Java執行安全佇列Queue

在Java多執行緒應用中,佇列的使用率很高,多數生產消費模型的首選資料結構就是佇列。Java提供的執行緒安全的Queue可以分為阻塞佇列和非阻塞佇列,其中阻塞佇列的典型例子是BlockingQueue,非阻塞佇列的典型例子是ConcurrentLinkedQue

Java多執行總結之執行安全佇列Queue

在Java多執行緒應用中,佇列的使用率很高,多數生產消費模型的首選資料結構就是佇列。Java提供的執行緒安全的Queue可以分為阻塞佇列和非阻塞佇列,其中阻塞佇列的典型例子是BlockingQueue,非阻塞佇列的典型例子是ConcurrentLinkedQueue,在實際

c++使用細粒度鎖以及傀儡節點的執行安全佇列

研究了一下執行緒安全的資料結構,參考了 《c++併發程式設計實戰》這本書上的程式碼寫了一個能夠編譯執行的版本這份程式碼解決的核心問題是在細粒度鎖的併發情況下可能出現的多個鎖同時鎖住一個節點解決的方法是使用傀儡節點即在佇列為“空”的情況下依然有兩個節點一個為空的頭節點一個為尾的

linux多執行程式設計(C):訊號量實現的執行安全佇列

用訊號量實現的執行緒安全佇列。 簡單有用的示例程式, 比起互斥量的實現在多執行緒時效率更好。 cir_queue.h /* * \File * cir_queue.h * \Brief * circular queue */#ifndef __CIR_QUEUE_H_

c++使用智慧指標的執行安全佇列

整理自C++併發程式設計實戰使用std::shared_ptr<>的執行緒安全佇列/* * threadsafe_queue_ptr.cpp * * Created on: Mar 2, 2018 * Author: [email p

C/C++ 執行安全佇列

一、簡介 執行緒安全是一個比較嚴肅的問題,如果處理不好,可能導致資料被破壞,程式崩潰等問題,如何來處理多執行緒的併發問題?在windows平臺有相應的api給你用於控制併發,如互斥鎖,訊號量,事件,臨界區等,定要熟練掌握,當然現在STL庫已強大到相容不同的硬體

ArrayListVector的區別,HashMapHashtable的區別以及執行安全的理解

就ArrayList與Vector主要從二方面來說. 一.同步性:Vector是執行緒安全的,也就是說是同步的,而ArrayList是執行緒序不安全的,不是同步的 二.資料增長:當需要增長時,Vector預設增長為原來一培,而ArrayList卻是原來的

ArrayListVector的區別,HashMapHashtable的區別以及執行安全的理解【轉】

http://www.cnblogs.com/xionglee/articles/1554701.html 就ArrayList與Vector主要從二方面來說. 一.同步性:Vector是執行緒安全的,也就是說是同步的,而ArrayList是執行緒序不安全的,不是同步的 二.資料增長:當需要增長時,Ve

執行與互斥鎖(C++11std::threadstd::mutex的用法)

執行緒 0 首先是曾經在MultiCMOS專案中用到的: #include <thread> //包含標頭檔案 class IDataProcessUnit { protected:

c++11 標準庫函數 std::move 完美轉發 std::forward

標準庫函數 這樣的 除了 值引用 sin 引入 語言 優先 ace c++11 標準庫函數 std::move 和 完美轉發 std::forward #define _CRT_SECURE_NO_WARNINGS #include <iostream>

基於std::mutex std::lock_guard std::condition_variable std::async實現的簡單同步隊列

有關 com urn list 占用空間 當前 條件變量 size 多線程 C++多線程編程中通常會對共享的數據進行寫保護,以防止多線程在對共享數據成員進行讀寫時造成資源爭搶導致程序出現未定義的行為。通常的做法是在修改共享數據成員的時候進行加鎖--mutex。在使用鎖的時