并发/行、多线/进程、IPC
文章平均质量分 58
线程、进程、IPC的使用以及常用知识点总结
一些并行、并发优化的手段
拾牙慧者
会点c++、python;
展开
-
C++链表并行排序实现(利用std::future)
除了使用std::async外,可以自己实现一下spawn_task函数,包装下std::packaged_task和std::thread。注意,一旦线程库判断任务过多,std::async()的实现可能并不是在新线程上操作,而是按照同步方式生成新任务,从而减小开销。代码中,链表的前半部分的排序不再由当前线程执行,而是通过std::async()在另一个线程上操作。std::partition操作耗时比较长,它是串行调用的,所以上述代码仍然有上升空间。可以更清晰地表达函数对象的返回类型,避免了使用。原创 2023-06-17 23:33:21 · 182 阅读 · 0 评论 -
实现线程安全的队列
使用了互斥量和条件变量来保证线程安全。中推入了 10 个整数,每个整数之间间隔 100 毫秒。假设我们忽略构造、赋值、互换、拷贝,那么只剩下3组操作。中取出了 10 个整数,并输出了每个整数的值。2:front、back,用于查询队列中的元素。在这个示例代码中,我们定义了一个生产者函数。中推入数据和从中取出数据。,并在两个线程中分别调用。原创 2023-06-13 15:42:00 · 2014 阅读 · 0 评论 -
递归加锁std::recursive_mutex使用
c++标准库为此提供了std::recursive_mutex,其工作方式与mutex类似,不同的是,其允许同一线程对某互斥的同一个实例多次加锁。是一个递归互斥量,它允许同一个线程多次对它进行加锁操作,而不会导致死锁。最后,线程会输出一条信息表示线程已经释放了互斥量,并解锁。有些场景中,我们需要让线程在同一互斥上多次重复加锁,而无需解锁。,然后输出一条信息表示线程已经锁定了互斥量。时,需要注意避免死锁和竞争条件的问题。的值大于 1,线程会递归地调用。,它会递归地调用自己,直到。原创 2023-06-12 22:46:01 · 449 阅读 · 0 评论 -
C++实现层级互斥锁
层级互斥锁实现原创 2023-06-12 11:34:43 · 441 阅读 · 0 评论 -
Call to deleted constructor of ‘std::thread‘ ‘thread‘
第一个代码返回的是一个引用,意味着返回的是 t 对象本身,而不是 t 对象的副本。第二个代码返回的是一个值,意味着返回的是 t 对象的副本。std::thread 类型的对象是不可拷贝的,不能通过值返回的方式来返回一个 std::thread 类型的对象。在std::thread中,它的拷贝构造、拷贝赋值操作符都被声明为delete,所以是不可复制的,不然会产生一些无法预料的错误。第一个代码返回的是一个 std::thread& 类型的引用,而第二个代码返回的是一个 std::thread 类型的值。原创 2023-06-06 17:21:02 · 416 阅读 · 0 评论 -
C++实现读写分离的双缓冲buffer
读写分离的双缓冲buffer有以下好处:1. 提高了并发读写的效率:在多线程环境下,读写操作是相互竞争的,读写分离的双缓冲buffer可以有效地减少读写之间的竞争,提高并发读写的效率。2. 减少了数据的拷贝:双缓冲buffer可以将数据从写缓冲区直接拷贝到读缓冲区,避免了中间数据拷贝的过程,提高了数据读写的效率。3. 提高了数据的安全性:双缓冲buffer可以避免读写操作的交叉,从而保证了数据的安全性。4. 提高了系统的稳定性:双缓冲buffer可以避免读写操作的阻塞,从而提高了系统的稳定性和可靠性原创 2023-03-22 23:20:48 · 2380 阅读 · 0 评论 -
C++将类序列化和反序列化到共享内存
【代码】C++将类序列化和反序列化到共享内存。原创 2023-03-22 22:40:06 · 187 阅读 · 0 评论 -
【Python】thread使用
1、Condition条件变量使用2、event通信3、Semaphore信号量使用4、setDaemon设置守护线程5、threadPool_map使用6、threadPool使用7、threadingTimer原创 2023-02-18 00:57:12 · 526 阅读 · 0 评论 -
【Python】进程、线程、协程爬虫性能比较
0、协程优缺点总结优点缺点Py协程基础1、svr api 用于测试2、依赖gevent的协程使用3、依赖asyncio的协程使用4、demo代码单进程多协程单进程多线程多进程多协程5、结果统计(取三次平均)原创 2023-02-15 21:32:59 · 1536 阅读 · 0 评论 -
对于线程并发模型与事件并发模型的思考
这里将以对话的形式进行:A:普通的线程是可以被其他线程中断掉的,而基于select、epoll的事件处理函数实际上是不可以被其他事件(线程)中断的。我这个理解对吗?B:图片里的应该是对是否可以并行,多路复用的说法,传统的io操作,可以在主进程里串行等待执行完再处理下面的逻辑,但逻辑上没有强相关的情况,可以并行去执行各种io(用户态),而主进程或其他子线程可以继续做其他事传统的io线程,主进程中是可以中断的,知道线程id,去中断就可以而select, epoll 主要是为了实现多路复用吧,配原创 2022-05-22 21:25:15 · 396 阅读 · 0 评论 -
关于并发概念的一些笔记
1、基于锁的并发数据结构1、并发计数器2、懒惰计数器3、并发链表4、并发队列5、并发散列表总结2、条件变量使用(POSIX)生产者/消费者 (有界缓冲区问题)覆盖条件扩展3、信号量使用二值信号量(锁)0值信号量(条件变量)生产者消费者问题读写锁哲学家就餐问题使用锁+条件变量实现信号量扩展4、并发问题总结1、预防循环等待2、使用非抢占锁3、完全避免互斥,使用CAS4、调度避免死锁5、检测死锁并恢复5、事件并发时间并发与线程并发的区别状态管理问题缺点原创 2022-05-22 21:19:31 · 423 阅读 · 0 评论 -
linux进程间通信快速入门【一】:管道编程
介绍 管道本质上就是一个文件,前面的进程以写方式打开文件,后面的进程以读方式打开。 这样前面写完后面读,于是就实现了通信。虽然实现形态上是文件,但是管道本身并不占用磁盘或者其他外部存储的空间。 在Linux的实现上,它占用的是内存空间。所以,Linux上的管道就是一个操作方式为文件的内存缓冲区。 管道分类:匿名管道、命名管道命令行中使用1、mkfifo或mknod命令来创建一个命名管道[root@VM-90-225-centos ~]# mkfifo pipe[root@VM-90-225原创 2022-03-12 16:22:04 · 1737 阅读 · 0 评论 -
CPU Cache对于并发编程的影响
文章目录引子CPU Cache对于并发的影响读写顺序对性能的影响字节对齐对Cache的影响小结引子下面给出两个极其相似的代码,运行出的时间却是有很大差别:代码一#include <stdio.h>#include <pthread.h>#include <stdint.h>#include <assert.h>#include<chrono>const uint32_t MAX_THREADS = 16;void* Thre原创 2022-02-15 11:09:20 · 565 阅读 · 0 评论 -
无锁队列设计思路以及简要代码
非并发的一写一读环形队列读指针:1、先判断是否有数据2、读取数据3、操作指针写指针:1、先判断空间是否足够2、写入数据3、操作指针·所以代码也十分简单:bool putqueue(void* pData){ ST_NODE* ptr = NULL; do { ptr = pWrite; if ((uiQueueSize - ((pWrite + uiQueueSize - pRead) % uiQueueSize) - 1 > 0原创 2022-02-15 09:41:10 · 630 阅读 · 0 评论 -
python数据库连接池使用
在转载|pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0这一篇中,我使用了方法一。接下来试试方法三,方法三和方法二其实意义差不多,但是对于数据库的连接并不是交由程序员管理而是交由连接池管理了,这里的对于connect的close并非真正的关闭连接,而是将连接重新放入连接池中。首先,我是用的数据库模块是:pymysql,没装的pip install pymysql。连接池我们使用DBUtils,使用前 p原创 2022-01-13 15:19:10 · 1396 阅读 · 1 评论 -
转载|pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0
原文链接:https://www.cnblogs.com/heiao10duan/p/9373237.html原因:使用了多线程,多线程共享了同一个数据库连接,但每个execute前没有加上互斥锁方法:方法一:每个execute前加上互斥锁 lock.acquire() cursor.execute(command,data) lock.release()方法二:每个线程拥有自己的数据库连接,即在线程调用函数中加上数据库连接代码方法三: 所有线程共用一原创 2022-01-13 14:31:51 · 1379 阅读 · 0 评论 -
python 线程异步执行踩坑
有个需求,一个线程在得到n个数据之后,异步地执行一个子线程函数,在子线程函数中完成数据库的打开、写入数据、关闭操作。在子线程函数返回前父线程先返回结果。version1百度了一下,参考这篇文章:python线程实现异步任务这个代码的执行结果如下:def update_mysql(id): executor.submit(do_update) return "ok" + str(id)def do_update(): time.sleep(3) print('sta原创 2022-01-10 11:35:50 · 1049 阅读 · 0 评论 -
异步日志系统设计demo
目录简单版本1优化版本1优化版本2对于QPS要求很高或者对性能有一定要求的服务器程序,同步写日志会对服务的关键性逻辑的快速执行和及时响应带来一定的性能损失,因为写日志时等待磁盘IO完成工作也需要一定时间。为了减少这种损失,一般采用异步写日志。本质上仍然是一个生产者与消费者模型,产生日志的线程是生产者,将日志写入文件的线程是消费者。如果有多个消费者线程,可能存在写日志的时间顺序错位,所以一般将日志消费者线程数量设置为1.简单版本1下面给出一个简单的版本:#include <iostrea.原创 2021-11-16 15:22:25 · 512 阅读 · 0 评论 -
使用mutex和条件变量实现信号量
c++提供了互斥量:mutex和条件变量:condition_variable,但是并没有信号量:semaphore。而linux和windows系统库会提供的。下面简单介绍一下信号量的特性,然后给出一个简单的demo,使用mutex + condition_variable 来实现信号量。信号量的定义:信号量是一个整数count,提供两个原子操作:P操作和V操作P操作(wait操作):count减1;如果count < 0,那么挂起执行线程V操作(signal操作):count加1;如果co原创 2021-11-16 13:24:25 · 1640 阅读 · 0 评论 -
C++多线程快速入门(五)简单线程池设计
目录设计思路主线程运行逻辑task以及taskpool设计详细流程讲解完整代码打印结果往期回顾设计思路线程池实际上就是一组线程,当我们需要异步执行一些任务时,经常要通过OS频繁创建和销毁线程,不如直接创建一组在程序生命周期内不会退出的线程。当有任务需要被执行时,线程可以自动地去拿任务并执行,在没有任务时,线程处于阻塞或者睡眠状态。我们选择队列存放任务,main函数中的thread作为任务的生产者,从队列尾部插入任务。线程池中的线程作为消费者,从队列头部获取任务。复杂考虑的话,当线程池的线程在处.原创 2021-10-25 19:25:26 · 737 阅读 · 0 评论 -
c++实现简单线程池代码
目录完整代码TaskPool.cppTaskPool.hmain.cpp完整代码TaskPool.cpp//// Created by LENOVO on 2021/10/25.//#include "TaskPool.h"#include <functional>std::mutex printMutex;TaskPool::TaskPool() : m_bRunning(false){}TaskPool::~TaskPool(){ remove.原创 2021-10-25 16:30:21 · 361 阅读 · 0 评论 -
C++多线程快速入门(四)shared_mutex以及读写锁应用
在前面的三讲中我们使用的mutex都是普通的std::mutex,这里介绍一下shared_mutex,版本为C++17std::shared_mutex的底层实现时操作系统提供的读写锁,在读多写少的情况下,该shared_mutex比mutex更加高效。它提供了常用的四种方法:lock和unlock分别用于获取写锁和解除写锁lock_shared和unlock_shared分别用于获取读锁和解除读锁写锁模式称为排他锁,读锁模式称为共享锁。c++11和c++14标准中分别引入unique_loc原创 2021-10-24 21:10:44 · 3198 阅读 · 0 评论 -
C++多线程快速入门(三):生产者消费者模型与条件变量使用
互斥锁完成#include <iostream>#include <deque>#include <thread>#include <mutex>std::deque<int> q;std::mutex mtx;static void produce(int val) { while(val--) { std::unique_lock<std::mutex> guard(mtx);原创 2021-10-23 14:37:51 · 373 阅读 · 0 评论 -
C++多线程快速入门(二)共享数据同步以及数据竞争
仅调用一次程序免不了要初始化数据,线程并发没有某种同步手段来控制,会导致初始化函数多次运行。c++11种提供仅调用一次的功能,首先声明一个once_flag类型的变量作为初始化标志,最好是静态、全局的,这样对于线程就是可见的了。然后调用专门的call_once()函数,以函数式编程的方式,传递这个标志和初始化函数,这样就可以保证,即使多个线程重入call_once(),也只能由一个线程会成功初始化#include <iostream>#include <thread>#in原创 2021-10-22 20:58:34 · 737 阅读 · 0 评论 -
C++多线程快速入门(一):基本&常用操作
目录case1:创建线程1 join、detachcase2:创建线程2 线程传参 传值或者传引用case3:创建线程 线程传参 仿函数作为参数case1:创建线程1 join、detach创建线程,并等该线程执行完毕,并且打印两个线程的id#include <iostream>#include <thread>using namespace std;void func() { cout << "hello , this is my thread,.原创 2021-10-21 18:57:55 · 919 阅读 · 0 评论 -
《线程管理:传递参数、确定线程数量、线程标识》
参考《c++ Concurrency In Action 》第二章做的笔记原创 2021-05-18 15:50:04 · 181 阅读 · 0 评论 -
《线程管理:线程基本操作》
目录线程管理启动线程与(不)等待线程完成特殊情况下的等待(使用trycath或rall)后台运行线程线程管理启动线程与(不)等待线程完成提供的函数对象被复制到新的线程的存储空间中,函数对象的执行和调用都在线程的内存空间中进行。class background_task{public: void operator()() const { do_something(); do_something_else(); }}; backgrou.原创 2021-05-17 20:00:04 · 233 阅读 · 0 评论