C++并发编程
C++并发编程
橙子砰砰枪
即使盗版书也看的津津有味
展开
-
C++线程编程-各种线程池
线程池存放任务的线程安全队列// 对比4.5 使用条件变量的线程安全队列的完整类定义// 包含shared_ptr实例#include <condition_variable>#include <mutex>#include <queue>#include <utility>#include <memory>template <typename T>class threadsafe_queue{private:原创 2022-04-09 17:54:49 · 1052 阅读 · 0 评论 -
C++线程编程-设计多线程版本的accumulate
非异常安全// std::accumulate的并行版本,非异常安全版本#include <numeric>#include <iterator>#include <thread>#include <vector>#include <functional>template<typename Iterator, typename T>struct accumulate_block{ void operator()原创 2022-04-08 22:38:58 · 883 阅读 · 0 评论 -
C++线程编程-设计无锁的并发数据结构
定义和结果使用互斥元、条件变量以及future 来同步数据的算法和数据结构被称为阻塞的算法和数据结构.调用库函数的应用会中断一个线程的执行,直到另一个线程执行一个动作.这种库函数调用被称为阻塞调用,因为直到阻塞被释放时线程才能继续执行下去.通常,操作系统会完全阻塞一个线程(并且将这个线程的时间片分配给另一个线程),直到另一个线程执行了适当的动作将其解锁,可以是解锁互斥元、通知条件变量或者使得future就绪.不使用阻塞库函数的数据结构和算法被称为非阻塞的.但是,并不是所有这样的数据结构都是无锁的,因此我原创 2022-03-27 11:28:35 · 1730 阅读 · 0 评论 -
C++线程编程-设计基于锁的并发数据结构
序列化多个线程轮流存取互斥元保护的数据,它们必须线性的而非并发的存取数据。高并发就意味着:更小的保护区域,更少的序列化,更高的并发潜能。设计基于锁的并发数据结构关键是要确保存取数据时要锁住正确的互斥元,并且要确保将锁的时间最小化.只用一个互斥元保护一个数据结构是很困难的.你需要确保此数据在互斥锁保护区域之外不会被存取,并且不会发生接口所固有的竞争现象.如果使用独立的互斥元来保护数据结构的独立部分,问题会变得更复杂,并且如果数据结构上的操作需要多个互斥元被锁住就有可能产生死锁.因此,设计有多个互斥元的数原创 2022-03-26 15:31:21 · 1503 阅读 · 0 评论 -
C++线程编程-内存顺序
内存顺序模型有六种内存顺序选项可以应用到原子类型上, memory_order_relaxed;memory_order_consume; memory_order_acquire;memory_order_release;memory_order_acq_rel; memory_order_seq_cst;它们代表三种模型:顺序一致 memory_order_seq_cst;获得-释放:memory_order_consume; memory_order_acquire;memory_orde原创 2022-03-24 15:01:15 · 2759 阅读 · 2 评论 -
C++线程编程-FP编程和CSP编程
FP/** * 使用操作同步来简化代码 - 带有future的函数式编程(FP) * * 才有函数式的方法来编写程序,并非直接在线程之间共享数据; * 而是每个任务都可以提供它所需要的数据,并通过使用future将结果传播至需要它的线程 * * future是使得C++FP风格的并发切实可行的最后一块拼图; * 一个future可以在线程之间来回传递,使得一个线程的计算结果以来于另一个的结果,而无需任何对共享数据的显示访问。 * * 这个风格的快速排序是用list,因为list的s原创 2022-03-21 16:04:26 · 584 阅读 · 2 评论 -
C++线程编程-时间控制和接受超时的函数
#include <chrono>#include <condition_variable>#include <mutex>#include <future>#include <iostream>using namespace std;using namespace chrono; // chrono的命名空间// 时间操作void fun0(){ // 匀速时钟 steady_clock; // 系统时原创 2022-03-21 11:16:22 · 1901 阅读 · 0 评论 -
C++线程编程-future和promise
future的使用方式:// 第一种:future和async// 第二种:future和packaged_task// 第三种:future和promise/* 使用promise在单个线程中处理多个连接 */// 这个promise和异步IO有类似的结构#include <future>void process_connections(connection_set &connections){ // 一直循环到没有连接 while (!done(c原创 2022-03-21 11:09:39 · 388 阅读 · 0 评论 -
C++线程编程-future和packaged_task任务包
// packaged_task<>模板// 可以将可调用对象和参数封装起来,并将它们和future绑定// 这样,只要某一个工作完成了,和它绑定的future就变成了就绪状态// 可以用做线程池的构建,用它实现多任务队列// 但是任务包(packaged_task)只适合用于一个简单函数的表达式调用,结果也是只来自这个函数。// 如果一个任务,无法用一个简单的函数表示,或者结果需要来自不同的任务,任务包就很难胜任,// 就需要第三种创建future的方式:promise/* 下面原创 2022-03-20 16:48:50 · 715 阅读 · 0 评论 -
C++线程编程-future和async
future使用future等待一次性事件,它和async连用。async异步运行一个函数,可能在新的线程中。// 使用futer等待一次性事件// 使用async 启动异步任务并返回结果#include <future>#include <iostream>#include <string>#include <functional>using namespace std;int find_thr_answer_to_ltuae(in原创 2022-03-20 15:45:10 · 475 阅读 · 0 评论 -
C++线程编程-使用互斥量构建一个线程安全队列
// 使用互斥量构建一个线程安全的队列#include <queue>#include <memory>#include <mutex>#include <condition_variable>using namespace std;template<typename T>class threadsafe_queue{private: mutable mutex mut; // 互斥元本质上必须是可变的 queu原创 2022-03-20 14:32:34 · 392 阅读 · 0 评论 -
C++线程编程-层级锁实现
// 层级锁的实现#include <mutex>#include <thread>#include <threads.h>#include <limits.h>class hierarchical_mutex{private: // 互斥元 std::mutex internal_mutex; // 初始化层次锁时给的层次值 unsigned long const hierarchy_value; //原创 2022-03-18 20:03:55 · 633 阅读 · 0 评论 -
C++线程编程-共享锁与条件变量
共享锁C++17提供。也是读写锁,shard_lock允许多个读操作,lock_guard即不允许写,也不允许读// 共享锁,读写场景多用// 共享锁是shared_mutex,通过锁定方式来决定是读是写,// 读用shard_lock锁定,这样不会阻塞其他读,但是会阻塞写// 写用lock_guard或者unique_lock锁定,会阻塞其他读和其他写// #include <vector>#include <shared_mutex>#include <原创 2022-03-20 13:38:01 · 840 阅读 · 0 评论 -
C++线程编程-所有权转移与单次调用
所有权转移如果一个锁通过参数传递或者move,或者通过参数返回,会发生锁的所有权转移,这是导致死锁的一个原因,如果不是特别需求,一般不会将锁的所有权转移。但是,转移锁的所有权有另一个好处,它可以延长锁的作用范围:// 通过unique_lock的移动机制,将锁的所有权转移给调用者,// 使得调用这可以在同一个锁的保护机制下执行额外的操作unique_lock<mutex> get_lock(){ extern mutex some_mutex; unique_lock原创 2022-03-20 13:34:42 · 324 阅读 · 2 评论 -
C++线程编程-互斥锁的死锁与死锁防止
产生死锁的原因:存在多个互斥锁,并且多线程之间竞争互斥锁多线程之间相互等待死锁避免:如果有多个互斥锁,可以使用lock将多把锁一起锁起来,并用lock_guard封装,自动释放锁如果确实需要分开锁,应确保上锁的顺序和解锁的顺序相反使用层级锁如果一个线程等待你,你就不要再等待它lock_guard<>没有任何功能,只是将互斥锁封装,在离开作用的时候自动析构,释放锁。不支持复制,不支持移动unique_lock<>支持上锁解锁功能,可以移动但不支持复制。原创 2022-03-20 13:26:20 · 669 阅读 · 0 评论 -
C++线程编程-物理核心线程数量与多线程开辟
物理核心线程数量thread::hardware_concurrency()静态成员函数,返回真正的可以并行的线程数量,在多核系统上,它可能是cpu的核心数量。过多的线程数量会增加上下文切换的负担,减少性能。开辟多线程mem_fn() 函数,可以将成员函数转为 函数对象。#include <thread>#include <iostream>#include <vector>#include <algorithm>#include <原创 2022-03-20 13:16:35 · 415 阅读 · 0 评论 -
C++线程编程-使用函数对象初始化thread对象
使用函数对象初始化thread对象有两种方式:使用初始化列表多加一层小括号使用函数对象的好处是可以将数据和函数封装起来。#include <iostream>#include <thread>using namespace std;class FUNC{public: void operator()(){ cout << "class FUNC"<<endl; }};int main(){ t原创 2022-03-20 13:05:48 · 976 阅读 · 0 评论 -
C++线程编程-线程分离和线程结合
《C++并发编程实战》上指出:在你的thread对象析构之前,你必须指明这个线程是分离的还是结合的。若 *this 拥有关联线程( joinable() == true ),则调用 std::terminate() 。如果线程被detach或者被join,那么joinable返回false,线程析构就不会调用terminnate,否则线程析对象析构的时候将调用terminante,导致整个进程结束。#include <thread>#include <iostream>vo原创 2022-03-20 13:02:29 · 473 阅读 · 0 评论 -
C++线程编程-参数传递与ref函数
thread库创建线程的时候,传递函数指针或者函数对象给参数,后续跟函数的参数,但是thread的构造函数其实和bind很类似:无论你这个线程函数是需要引用参数,还是需要值参数,起初传递给thread对象的都是值传递,而thread对象把值传递给线程函数的时候才会进行引用传递或者值传递,所以说,无论怎样都会有一次拷贝操作,而在thread或者bind对象析构的时候,这个值就会消失,从而造成一种假象:我明明传递了引用,而这个引用的值在线程函数里的改变却没有影响到原来的值。解决方法:使用ref函数,表明使用左原创 2022-03-20 12:55:54 · 771 阅读 · 1 评论