![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程/多进程
zhjs_abc
不要在可以吃苦的时候而选择了安逸
展开
-
TCP/IP网络编程学习笔记(十二)
重叠IO模型(Overlapped IO)中,IO操作本身是异步的,与调用IO函数的线程无关。也就是说,调用IO的线程只是发起IO操作,IO操作本身是由其他线程完成的,调用IO的线程可以同时干其他事情。不过,当确认IO操作是否完成时,默认还是需要调用IO的线程来确认。如果添加了回调函数,也就是IO操作完成后自动执行一个后处理函数,此时这个后处理函数也是由刚才发起IO请求的线程来执行的,并且只有当发起IO请求的线程执行了等待函数(比如WaitForSingleObjectEx(),WaitForMulti..原创 2020-09-23 15:52:03 · 87 阅读 · 0 评论 -
Windows下使用CreateThread()和_beginthreadex()的区别
根据《Win32多线程程序设计》中的介绍,当创建的子程序中包含某些C runtime 函数时,不应该使用CreateThread()。如果主线程以外的任意新建的线程中包含以下操作,则应该使用多线程版本的C runtime library,并使用_beginthreadex()和_endthreadex():在C程序中使用malloc()和free(),或者在C++程序中使用new()和delete();调用stdio.h或io.h中声明的任何函数,包括fopen()、open()、getchar..原创 2020-09-21 10:30:17 · 349 阅读 · 0 评论 -
TCP/IP网络编程学习笔记(十)
Linux下如果想使用线程安全的标准库函数,则要么在头文件上方定义一个枚举类型:#define _REENTRANT // 表示可重入#include <...>要么在编译的时候添加宏-D_REENTRANT:gcc -D_REENTRANT test.c -o test -lpthread详情请看:LINUX C编程中_REENTRANT宏的作用;注意,Linux下编写多线程程序在编译时最好都加上宏-D_REENTRANT;不管是信号量还是互斥体,在使用前都要in..原创 2020-09-19 19:20:51 · 244 阅读 · 0 评论 -
TCP\IP网络编程学习笔记(四)
通过fork函数创建的子进程能够继承父进程中所有变量的值,但是一旦创建后,父进程和子进程中的变量不再有任何关系,即使是一个全局变量,父进程和子进程都会有不同的副本,修改并不会影响另一个进程中的这个全局变量的值;产生僵尸进程的原因:子进程使用exit()函数返回一个返回码(即exit()函数里面传入了实参);子进程main函数(每个进程最后都会从main函数正常返回的啦)通过return语句返回一个值。其根本原因是上述两种情况都会将返回的值传给操作系统,而操作系统不会销毁子进程,直到把..原创 2020-09-15 10:36:39 · 78 阅读 · 0 评论 -
关于三种内存序的一些注意点
RWM操作中含有两种操作,一个load操作,另一个store操作。然而,RWM操作的函数只支持传入一个内存序形参来同时表示store操作和load操作(那些CAS操作能够传入两个内存序形参并不是分别给load操作和store操作用的,是分别对应操作失败和操作成功的),因此,如果RWM函数中内存序传入的是acquire,consume内存序,则此内存序只能对RWM中的load部分有效,如果传入的是release,则只对RWM中的store有效,如果传入的是acq_rel或者seq_cst,则能同时对R...原创 2020-09-05 16:30:54 · 442 阅读 · 0 评论 -
高并发栈(stack)数据结构的无锁实现和超详细分析过程
一、创建无锁栈1. 实现无锁栈的基本结构众所周知,栈是一个后进先出(LIFO)的数据结构,栈只需要直接访问栈首元素即可,因此,可以使用最简单的单向链表来实现栈。向栈中加入元素的步骤为:创建一个新的节点;将新节点的next指针指向栈首(head元素);将head指向新节点;上述过程在单线程中很完美,但是在多线程中就有可能发生数据竞争:线程1将新节点1的next指向head之后,发生线程切换,线程2将自己的节点2的next指向head,并将head指向节点2。此时线程1切换回来继续执行,将新的h原创 2020-09-04 16:37:23 · 1446 阅读 · 2 评论 -
基于细粒度锁的高并发字典(查找表)的实现和分析过程
本文内容一、前言二、细粒度锁高并发查找表的实现1. 并发查找表的粗略实现2. 底层数据结构的高并发实现三、总结同博文基于细粒度锁的高并发队列的超详细实现和分析过程类似,也是对《C++ Concurrency In Action 2nd》中的例子的翻译及解析。本文相当于对前文的延续。废话不多说,直接开始。一、前言上一篇文章分析了队列的高并发实现过程,由于队列相对简单,所以相对来说比较容易实现。本文尝试使用细粒度锁来实现复杂的数据结构:查找表(即map)。设计查找表最复杂的莫过于对迭代器的并..原创 2020-08-25 16:46:21 · 284 阅读 · 0 评论 -
基于细粒度锁的高并发队列的超详细实现和分析过程
本文内容一、前言二、线程安全的队列的实现1. 使用锁和条件变量来实现线程安全的队列2. 使用细粒度锁和条件变量来实现线程安全的队列使用细粒度锁来实现队列的高并发性引入条件变量来实现队列的可等待接口三、总结一、前言最近在看《C++ Concurrency In Action 2nd》,发现里面一节基于锁来实现高并发的队列讲解的非常棒,并且里面体现了很多细节,而且还给出了一些实现高并发数据结构的指导方针,因此觉得很不错,就在此边翻译边讲解一下。本教程从比较粗糙的设计开始,一步一步转向更精细的设计,..原创 2020-08-22 18:11:44 · 676 阅读 · 1 评论 -
C++11内存模型完全解读-从硬件层面和内存模型规则层面双重解读
acquire-release:release-sequence rule:指线程1中对原子变量进行store操作,线程2对此原子变量执行RMW操作,线程3对此原子变量页执行RMW操作,线程4与线程3类似…线程n对此原子变量执行load操作或者RMW操作。其中上述所有的store操作都是用的release、acq_rel、seq_cst语义,而所有的load作都用的acquire、acq_rel、seq_cst、consume语义,且除了最后一个线程中的RMW不能用relaxed语义外,其他任何中间线程原创 2020-08-18 16:43:11 · 4575 阅读 · 14 评论 -
C++11中的线程感知内存模型(thread-aware memory model)中内存序(memory order)的讲解以及底层原理剖析
好吧,并不是我来讲解,最近看了几篇博文,从硬件层面分析了内存序以及各种同步的必要性,感觉讲的非常好,因此这里做一个中转站,让给多的人看到。这几篇文章都是知乎上的:高并发编程–多处理器编程中的一致性问题(上);高并发编程–多处理器编程中的一致性问题(下);高并发编程–线程同步;C++ memory order与happen-before。此外,知乎上也有其他不少文章讨论相关问题,大家都可以去看看!...原创 2020-08-05 22:54:55 · 442 阅读 · 0 评论 -
C++11内存模型和原子类型的简述
本文并非原创,转载于知乎文章C++11 - atomic类型和内存模型,请支持原创!!!概述:本文是两本书的读书笔记,一本是《深入理解C++11 - C++11新特性解析与应用》(下文简称书1),另外一本是《C++ Concurrency In Action》(英文版)(下文简称书2)。作者在Windows平台下使用多线程技术进行工业自动化领域开发工作,深知多线程程序开发、测试和调试及调优,是件痛苦的事情——深夜调试/失眠、抓狂……2000年之后,依靠CPU频率提升加速软件运行速度的免费午餐结束了转载 2020-08-03 16:03:02 · 471 阅读 · 0 评论 -
C++中有关多线程和并发相关知识点梳理
1. thread类:(1). 创建线程:void f1();void f2(int);void f3(std::vector<int>&);class A{public: void fa1(std::vector<int>&); operator()(std::vector<int>&); }void ff(A);//...std::vector<int> vi;A a;std::thread原创 2020-07-31 23:58:32 · 333 阅读 · 1 评论 -
C++中条件变量std::condition_variable的唤醒说明
std::condition_variable的notify_one()以及notify_all()只是用于唤醒被wait...()函数阻塞的线程,假如wait...()函数没有被阻塞,比如wait(lock, func)中的func函数始终返回true,则wait函数就始终不会被阻塞,则根本就不需要唤醒。...原创 2020-07-31 12:31:09 · 1804 阅读 · 0 评论 -
C++ 中死锁的产生及解决
死锁产生的必要条件:互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1原创 2020-07-28 16:09:13 · 2093 阅读 · 0 评论 -
采用保护机制(如互斥体)来保护数据需要注意的点
在代码编写时,可以使用互斥体的方法来保护某个函数操作受保护数据的排他性,使得同一时间只能有一个线程来修改数据。不过需要注意:如果受保护的代码区域所对应的函数向函数外部传送了受保护数据的指针或者引用,则这种保护就根本没生效,因为可以在此保护区域外来修改共享变量;在受保护区域内使用回调函数来处理共享数据也会非常危险,因为用户可能传入一个自定义函数,从而把受保护的数据用指针或者引用方式通过此函数传输到外部并赋值给一个外部变量。...原创 2020-07-22 16:42:20 · 179 阅读 · 0 评论 -
避免条件竞争的三种方法
1. 采用某种保护机制来保护数据,确保只有进行修改的线程才能看到不变量被破坏时的中间状态;2. 使用无锁编程;3. 使用事务来处理更新,将数据和读取都存储到事务日志中,然后将之前的操作合并为一步,再进行提交。当数据被另一个线程修改后,或处理已经重启的情况下,提交就会无法进行。...原创 2020-07-22 16:04:10 · 1881 阅读 · 0 评论