C++11 STL 多线程
文章平均质量分 79
时空-大海水
喜欢c++,喜欢一起研究
展开
-
《C++ Concurrency in Action》笔记24 std::atomic<T*>、std::atomic<整型>
5.2.4 std::atomic相关操作某种类型指针的原子类型就是std::atomic,就像bool类型的原子类型是std::atomic一样。接口从本质上来说是一样的。它不支持拷贝构造和拷贝赋值,尽管他可以从对应的非原子类型的指针构造以及赋值。它也有load(),store() ,exchange(),compare_exchange_weak(),以及compare_exchang原创 2017-09-28 18:54:04 · 485 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记5 std::thread::id
线程id由类std::thread::id来表示,获取线程id的方法有两种:1.std::thread的成员函数get_id()。2. 静态函数std::this_thread::get_id()。id支持==、objects of type std::thread::id offer the complete set of comparison operators, whi原创 2017-09-15 21:34:19 · 317 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记6 Avoiding problematic race conditions
阻止竞争问题的几种办法:1.保证每一个时刻只有一个线程在修改数据。C++标准提供了若干机制。2.无锁编程(lock-free programming),本书第七章介绍。3.software transactional memory ( STM ),本书未做讲解。原创 2017-09-16 14:21:47 · 259 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记7 mutex(1)
C++标准库提供了std::mutex类作为互斥量,提供了lock()和unlock()成员函数,但是不建议直接使用这两个成员函数。如果漏写其中之一将导致错误,包括产生异常时的处理,都很容易出错。C++提供了一个类模板std::lock_guard,它对一个mutex实现了RAII机制,在构造时锁定mutex,析构时解锁mutex。保证在绝大多数情况下每一次lock都对应一个unlock。原创 2017-09-16 14:39:48 · 199 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记7 mutex(2)pop和top问题
虽然在类中封装mutex可以对数据进行并发保护,但是有些时候光对每个操作进行保护是不够的。看下面的代码:template >class stack{public:explicit stack(const Container&);explicit stack(Container&& = Container());template explicit stack(const Alloc原创 2017-09-16 16:18:21 · 326 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记7 mutex(3)pop和top问题之方案
接着上一篇笔记,如何解决,top、pop问题。方案一让pop()以参数的形式返回一个引用。std::vector result;some_stack.pop(result);这种方案在大多数情况下都能正常工作。但是它有个严重的缺点,就是需要再调用pop前先构造一个值的实例。有时,这是不切实际的,因为这需要花费时间或资源。另一方面,这也不总是可行的,因为构造一个示例所需的参数在某个原创 2017-09-16 17:50:29 · 275 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记7 mutex(3)pop和top问题之示例
采用上一篇所说的方案一和方案三定义的一个线程安全的stack,它其实是个stack的包装类,代码如下:struct empty_stack : exception{ const char* what() const throw() { return "the stack is empty"; };};templateclass threadsafe_stack{priva原创 2017-09-16 18:38:34 · 227 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记8 死锁(1)
就像之前关于top和pop的讨论,他的问题本质上来说是因为lock了太小的单元,保护并不能覆盖几个操作的组合。但是,另一方面,如果lock了太大的范围,同样也能导致问题。极端的情况就是一个全局mutex对象保护了所有的共享数据。在一个存在着大量共享数据的系统中,这将抵消并发带来的任何效益增值,因为它强迫在同一时刻只能运行一个线程,即使这些线程访问的是不同的共享数据。Linux内核的第一个版本就是被原创 2017-09-16 19:01:32 · 308 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记8 死锁(2)避免死锁
死锁大多由lock引起,但是有时候没有执行lock操作仍然可以引起死锁。例如,两个线程互相jion导致的死锁;或者多个线程形成的一个循环join导致的死锁。避免死锁的方法可以归结为一句话:不要等待另一个线程,如果它此时正在等待你。下面是作者提供的如果识别和消除死锁的几个准则:一、避免嵌套锁首先的建议是,不要重复锁定。如果你已经锁定了就不要再次锁定。如果想同时对多个对象进行锁定操作,那么使用原创 2017-09-16 23:28:15 · 295 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记4 hardware_concurrency()
One feature of the C++ Standard Library that helps here is std::thread::hardware_concurrency() . This function returns an indication of the number of threads that cantruly run concurrently for a gi原创 2017-09-15 20:08:07 · 1236 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记4 vector<thread>
将多个thread对象放到vector中,之后顺序执行join。看如下示例:vector v_id(20);void f(int i){ v_id[i] = i;}void call_by_main(){ vector v; for (int i = 0; i < 20; ++i) { v.push_back(thread(f,i)); } for_each(v.be原创 2017-09-15 17:38:45 · 1136 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记28 无锁并行数据结构
7 设计无锁并行数据结构mutex是一种强大的工具,可以保证多个线程安全访问数据结构。使用mutex的目的很直接:访问被保护数据的代码要么锁定了mutex,要么没有。然而,它也有不好的一面,错误的使用它会导致死锁,你也看到了基于锁的队列、查询表例子,所得粒度可以影响并发性能。如果你能写不使用锁的数据结构,那就可以避免这些问题。这样的数据结构叫做无锁数据结构。在这一章,你将看到如何使用第原创 2017-10-04 23:01:17 · 869 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记 前言
本人刚刚开始看《C++ Concurrency in Action》这本书的英文原版。很多多线程知识还处于比较模糊的状态,因此决定在看书的同时写点测试小程序,在这里做一下记录,发出来与大家一起讨论。有些地方会引用作者的原话,并且本着谨慎的态度发表自己的看法。如有问题还望不吝赐教,欢迎大家来讨论。本文本着实用的目的,所以别指望它多么正规,多么好看,实用才是硬道理。QQ:114211200原创 2017-09-15 10:20:48 · 383 阅读 · 2 评论 -
《C++ Concurrency in Action》笔记1 join和detach
void f(){}int main(){ thread t(f);//做一些事情 t.join();//或者detach//做一些事情 system("pause"); return 0;}当创建一个线程后,最终要对该线程执行jioin或detach操作。在本程序中, t.join();后代码将不再往下执行,直到t线程入口函数执行完,原创 2017-09-15 11:16:27 · 491 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记2 线程函数传参(1)
看程序1:namespace mparam{ class A { public: A(const char *c) { cout str = c; } string str; }; void f(const A &a) { cout cout cout } void call_by_main(原创 2017-09-15 13:32:25 · 312 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记2 线程函数传参(2)
std::ref的作用是声明要传递的参数是以引用的方式传递的。先看下面的程序:namespace mparam2{ class A { public: A(const string &s) :str(s) {} A(const A &other) { cout << "cur thread id:" << this_thread::get_id() << ":"原创 2017-09-15 14:09:49 · 231 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记2 线程函数传参(3)类成员函数
示例1:class A{public: A(int m) :n(m) {}; void f() { cout << n << endl; } int n = 0;};void call_by_main(){ thread t(&A::f, A(123)); t.detach(); system("pause");}没什么好说的,就是这么调用。输出结果原创 2017-09-15 14:46:25 · 250 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记2 线程函数传参(4)move
有时,要给线程函数传递的参数是不可拷贝的,比如:std::unique_ptr、std::ifstream等,但是它们可以被move。看下面的程序:void f(unique_ptr u){ cout << *u << endl; cout << (*u = "456") << endl;}void call_by_main(){ unique_ptr p(new string原创 2017-09-15 15:06:18 · 229 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记3 move线程对象
线程对象本身是不可以拷贝的,只能move。看下面的程序:void some_function(){}void some_other_function(){}void call_by_main(){ std::thread t1(some_function); std::thread t2 = std::move(t1); t1 = std::thread(some_othe原创 2017-09-15 15:31:36 · 292 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记9 std::unique_lock源码分析
std::unique_lock提供与std::lock_guard 相同的RAII -style锁管理机制,但是更加灵活。要想理解unique_lock,最好的办法就是看他的源码(vs2013):template class unique_lock { // whizzy class with destructor that unlocks mutexpublic: typede原创 2017-09-17 13:34:56 · 456 阅读 · 1 评论 -
《C++ Concurrency in Action》笔记10 选择合适的lock粒度
先看一个简单的示例:class X{public: string some_detail; std::mutex m;public: X(string const& sd) :some_detail(sd) {} friend void swap(X& lhs, X& rhs) { if (&lhs == &rhs) return; std::unique_loc原创 2017-09-20 12:06:53 · 295 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记20 带有消息传递的多线程实现--ATM
一个使用子线程执行任务的简单实现:templatestd::future::type> spawn_task(F&& f, A&& a){ typedef std::result_of::type result_type; std::packaged_task task(std::move(f))); std::future res(task.get_future());原创 2017-09-26 10:14:39 · 680 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记21 内存模型基础
截止到目前,我们只是讨论了高层级的操作,下面我们将讨论低层级的操作:C++内存模型和原子操作。很多程序员都没有注意到一种非常重要的C++11特性。那不是词法特性,也不是新的库支持,而是新的多线程相关的内存模型。没有内存模型去确切的定义基本结构如何工作,那么之前讨论的所有同步机制就无法实现。大部分人不关心这点的原因是:使用了mutex、condition_variable、future来做同步后原创 2017-09-26 23:08:07 · 564 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记22 std::atomic_flag
std::atomic_flag是最简单的标准原子类型,它代表一个bool状态。这个状态只有两个值:set和clear。到目前为止,我还没发现在在哪使用它,除非再特殊的场景下。 std::atomic_flag对象必须被ATOMIC_FLAG_INIT初始化,它会将std::atomic_flag初始化为clear状态。这是没有选择余地的,atomic_flag总是以clear状态初始化。原创 2017-09-27 21:51:48 · 287 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记23 std::atomic<bool>
5.2.3 std::atomic的相关操作最基本的内置类型就是std::atomic,这是个比atomic_flag更为全面的bool量。尽管它仍然不支持拷贝构造和拷贝赋值,但是它可以从一个非原子类型的bool量构造,也可以用一个非原子类型来给std::atomic赋值:std::atomic b(true);b=false;需要注意的是,复制操作并不像我们平时那样返回对象引用,而原创 2017-09-28 12:14:50 · 4056 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记27 基于锁的并行数据结构
6 设计基于锁的并行数据结构如果一个数据结构可以被多个线程访问,要么因为他的数据是一直不变的因而不需要做任何同步手段,要么则需要做同步手段以保证不同线程能够正确访问。一种方法就是使用一个独立的mutex然后在外部锁定它,保证数据被保护,就像我们在第3章和第4章中看到的那样;另一种方法是将数据结构本身设计成可并行访问的。当我们设计一个支持并行访问的数据结构时,你可以使用多线程应用的基本构原创 2017-10-02 11:21:31 · 558 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记26 原子操作和强制排序
5.3 同步操作和强制排序假如你有2个线程,一个填充数据,另一个读取数据。它们通过一个标志位来达到同步的目的:std::vector data;std::atomic data_ready(false);void reader_thread(){ while (!data_ready.load())//(1) { std::this_thread::sleep(std::mi原创 2017-09-29 15:03:04 · 939 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记29 设计并行代码(1)
8 设计并行代码在设计并行代码时要比设计顺序代码时考更过,不仅包括封装、耦合、聚合,而且需要考虑哪些数据需要共享,怎样同步访问数据,哪些线程需要等待其他线程完成工作等等。在这一章,我们将聚焦于这些问题,着眼于高层级(也是基本的)考虑多线程用法,哪些代码执行在哪些线程上,它们对代码清晰度的影响,以及探寻作为共享数据的数据结构的细节以提升性能。首先来看看如何在线程间划分工作。8.1原创 2017-10-13 12:00:40 · 612 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记25 std::atomic<>类模板、全局函数
现在我们已经了解了所有基本的原子类型,它们都是std::atomic类模板。5.2.6 std::atomicstd::atomic最后,这个类型还需要具有按位可比性(bitwise equality comparable)。这个要求是与赋值操作并驾齐驱的,它不只要求可以使用memcpy() 进行拷贝,还要能够使用memcmp()进行比较。这些要求最终的目的是为了能够正确的执行“比较/原创 2017-09-28 22:49:10 · 1150 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记19 限时等待、FP并行编程
有时,当你阻塞以等待一个事件的发生时,你希望对等待的时间做一些限制。这时,一些具有时间限制的等待函数可以满足你的要求。限时等待限时等待允许你在交互操作中告诉对方,你“仍然活着”;或者如果用户点击了取消按钮,仍然可以结束等待状态。有两种超时方式你可以选择:一种是时间长度,另一种是时间点。大多数的等待函数都同时提供了这两种方式,设置等待时间长度的函数以_for作为后缀,而设置等待的时间点的原创 2017-09-25 15:55:36 · 350 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记18 std::shared_future
std::future有个限制,那就是只能被一个线程等待。如果你希望从多个线程等待一个相同的事件,那就应该使用std::shared_future。等待多个线程尽管future对数据从一个线程到另一个线程传送作了所有的必要处理,但是调用同一个future实例的成员函数的不同线程却不会彼此同步。如果你访问单一的来自多个线程的fuure实例,没有附加的同步手段,那么你将导致数据竞争。因为,一个原创 2017-09-25 15:01:50 · 919 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记11 同步初始化
有时,不太好确定锁定的粒度究竟应该多大,因为并不是所有对共享数据结构的请求都在一个层级上。此时,另一种机制也许可以代替普通的mutex。一种极端的情况是,共享数据仅仅在初始化时需要同步,初始化之后就再也不需要做同步操作了。这也许是因为:要么这是一种只读数据;要么它的所有操作都隐含着相应的保护机制。再者,纯粹为了保护数据初始化而使用mutex是没必要的,也是有损性能的。为此,C++标准提供了一种原创 2017-09-20 18:06:29 · 214 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记12 boost::shared_mutex
如果多线程访问的数据在大部分时刻都是被读,只有极少的几率被写,那么如果使用mutex可能会导致效率低下。但是C++11并没有相应的手段,尽管一种方案被提交给C++委员会,但是没有通过。它就是boost::shared_mutex,它不是灵丹妙药,而且他的效率依赖于计算机的核数以及线程处理的工作量。对于超大规模的系统来说,它是具有实在的益处的。对于需要做数据更新操作的线程,可以使用lock_gu原创 2017-09-20 22:48:08 · 547 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记13 std::recursive_mutex
对于一个std::mutex对象,如果你已经锁定它了,那么在unock()之前你就不可以再次对他执行lock()函数。但在有些情况下,可能希望在解锁前多次锁定一个mutex。对于这种情况,C++标准库提供了std::recursive_mutex。他与std::mutex用法一样,除了可以在一个线程中多次lock一个recursive_lock。但是它要求,在其他线程使用这个lock前,你必须保证原创 2017-09-20 23:17:16 · 2281 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记14 condition_variable
有时候,你不仅仅需要保护数据,还要在线程之间做同步执行。一个线程可能需要等待一个线程完成一个任务后再继续执行。例如:一个线程等待一个时间发生或者一个条件达成。尽快通过周期判断一个标志或者一些保存在共享数据中的类似的东西可能达到目的,但这并不是理想的做法。在线程间进行同步操作是如此的寻常,C++标准库提供了灵活的手段:condition variables和futures。假如你正坐在旅行的火车原创 2017-09-21 09:33:33 · 329 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记15 a thread-safe queue with condition variable
我们在标准std::queue上做出如下修改:1.将pop()和top()合并为一个函数。2.新增一个 try_pop()函数,不管是否pop成功都立刻返回。2.新增一个wait_and_pop()函数,一直等待,直到有元素可以pop。一个不是很完整的简化示例代码如下:templateclass threadsafe_queue{private: muta原创 2017-09-21 19:57:41 · 355 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记16 future
当线程需要等待一个数据的有效性时,condition_variable就显得不是很适合了,此时应该使用futures。想象你将要坐飞机去休假,办完手续后你需要几个小时去等待飞机起飞。此时你会选择做一些事情来打发时间,比如喝咖啡、看书等等,但根本上讲你只为等一件事:登机。而且,你本次等的航班是唯一的。下次你再旅行就要等待另一趟航班。C++标准库将这种一次性事件称作一个future。如果一个线原创 2017-09-21 21:03:02 · 259 阅读 · 0 评论 -
C++11 多线程之传递package_tast讨论
《C++ Concurrency In Action》中有一段这样的示例:许多GUI框架的GUI更新都是通过一个指定的线程来实现的,所以其他线程如果想更新界面必须给指定的线程发送信号。std:packaged_task提供一种方法,可以不用定义自定义消息,如下:std::mutex m; std::deque > tasks; bool gui_shutdown_message_r原创 2017-09-23 20:44:19 · 735 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记17 promise
当你编写一个需要处理很多网络连接的程序时,你往往倾向于将在每个线程中处理一个连接,这样更容易设计和实现。这比较适合少量连接的情况。随着连接数的增加,这变得越来越不可能,太多的线程消耗过多的系统资源,以及潜在的引发频繁的上下文切换(当线程数操作可硬件能提供的最大并发数时),影响效率。在极端的情况下,可能将操作系统资源耗尽。在这种维护大量网络连接的应用中,通常的做法是使用少量的线程来处理连接,每个原创 2017-09-24 10:59:31 · 403 阅读 · 0 评论 -
《C++ Concurrency in Action》笔记30 高级线程管理——线程池及中断线程
9 高级线程管理在之前的章节,我们通过直接创建std::thread对象来管理线程。有几处你已经看出,这是不可取的,因为之后你必须管理线程对象的生命期,以及确定适合该问题的线程数和当前的硬件,等等。理想的情况是,你可以最大程度的将代码分成可以并行执行的小块,把它们交给编译器和标准库,然后说:“把它们并行化以获得最佳性能”。这些例子中的另一个常见问题就是,你可能使用了多个线程来解决一个问原创 2017-10-20 17:51:26 · 1366 阅读 · 1 评论