C++ 多线程与内存模型资料汇
参考阿里云文章
参考linux kernel perfbook
参考C++并发编程
并发编程算法总体上分为两大类
blocking algorithms
non-blocking algorithmsblocking algorithms
1)blocking
一个方法被称为阻塞的,即这个方法在其演进过程中不能正常运行直到其他(占有锁的)线程释放。
2)starvation-free(也称无闭锁)
只有当底层平台/系统提供了明确的保障以后讨论这个性质才有意义。
希望进入互斥区的线程最终都能进入。non-blocking algorithms (参见non-blocking algorithm)
1)Obstruction-Free(Maurice Herlihy,Mark Moir和Victor Luchangco所提出的Double-ended Queue)
Obstruction-free 是指在任何时间点,一个孤立运行线程的每一个操作可以在有限步之内结束。只要没有竞争,线程就可以持续运行,一旦共享数据被修改,Obstruction-free 要求中止已经完成的部分操作,并进行回滚,obstruction-free 是并发级别更低的非阻塞并发,该算法在不出现冲突性操作的情况下提供单线程式的执行进度保证,所有 Lock-Free 的算法都是 Obstruction-free 的。
2)Lock-Free
Lock-freedom 指的是整个系统作为一个整体一直运行下去,系统内部单个线程某段时间内可能会饥饿,这是比wait-freedom弱的并发级别,但系统整体上看依然是没有阻塞的。所有wait-free的算法显然都满足lock-free的要求。
3)Wait-Free
Wait-freedom 指的是每一个线程都一直运行下去而无须等待外部条件,整个流程中任何操作都能在一个有限的步骤内完成,这是最高的并发级别,没有任何阻塞。
0.并发的相关知识点
0.1 并行与并发
- 计算机中的并发,指的是在单一系统中,同时执行多个独立的活动。对于多核系统,它们在同一时刻进行的活动,则称为并行。
希望进入互斥区域的线程最终都能够进入互斥区域(即使之前在互斥区中的线程意外停止了)。
0.2 多进程和多线程并发
多进程并发
多个进程独立地运行,它们之间通过进程间常规的通信渠道传递讯息(信号,套接字,文件,管道等),这种进程间通信不是设置复杂就是速度慢,这是因为为了避免一个进程去修改另一个进程,操作系统在进程间提供了一定的保护措施,当然,这也使得编写安全的并发代码更容易。
运行多个进程也需要固定的开销:进程的启动时间,进程管理的资源消耗。多线程并发
线程就像轻量级的进程,每个线程相互独立运行,但它们共享地址空间,所有线程访问到的大部分数据如指针、对象引用或其他数据可以在线程之间进行传递,它们都可以访问全局变量。进程之间通常共享内存,但这种共享通常难以建立且难以管理,缺少线程间数据的保护。因此,在多线程编程中,我们必须确保每个线程锁访问到的数据是一致的。
0.3 同步和异步
0.3.1 同步和异步概念
同步
就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。异步
当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
如果执行部件用状态来通知,那么调用者就需要每隔一定时间检查一次,效率就很低。如果是使用通知的方式,效率则很高,因为执行部件几乎不需要做额外的操作。至于回调函数,其实和通知没太多区别。
0.3.2 同步传输和异步传输概念
同步传输
通常,同步传输是以数据块为传输单位。每个数据块的头部和尾部都要附加一个特殊的字符或比特序列,标记一个数据块的开始和结束,一般还要附加一个校验序列 (如16位或32位CRC校验码),以便对数据块进行差错控制。所谓同步传输是指数据块与数据块之间的时间间隔是固定的,必须严格地规定它们的时间关系。异步传输
通常,异步传输是以字符为传输单位,每个字符都要附加 1 位起始位和 1 位停止位,以标记一个字符的开始和结束,并以此实现数据传输同步。所谓异步传输是指字符与字符(一个字符结束到下一个字符开始)之间的时间间隔是可变的,并不需要严格地限制它们的时间关系。
异步传输又称为起止式异步通信方式,其优点是简单、可靠,适用于面向字符的、低速的异步通信场合。例如,计算机与Modem之间的通信就是采用这种方式。它的缺点是通信开销大,每传输一个字符都要额外附加2~3位,通信效率比较低。例如,在使用Modem上网时,普遍感觉速度很慢,除了传输速率低之外,与通信开销大、通信效率低也密切相关。
0.3.3 阻塞和非阻塞、同步和异步
同步
执行一个操作之后,等待结果,然后才继续执行后续的操作异步
执行一个操作后,可以去执行其他的操作,然后等待通知再回来执行刚才没执行完的操作
访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。阻塞
进程给CPU传达一个任务后,一直等待CPU处理完成,然后才执行后面的操作非阻塞
进程给CPU传达任务后,继续处理后续操作,隔断时间再来询问之前的操作是否完成。
进程/线程要访问的数据是否就绪,进程/线程是否需要等待。
1.多线程相关的头文件
1.1 thread support library
- 这些库包括
<thread>
<mutex>
<condition_variable>条件变量
<future> - “Thread support library”可以简单想象成POSIX线程库的OO版本,对常用的Threads、Mutex、Condition Variables、Futures等概念进行了很好的封装,其实它的前身就是Boost::Thread.
1.2 atomic operations library
- <atomic>
- “Atomic operations library”顾名思义,其实就是原子操作库。而在以往,我们往往需要借助汇编语言或者第三方线程库方能实现。atomic对于多线程编程,尤其是lock-free算法,其重要性不言而喻.
- 并非所有的atomic内置类型操作均是lock-free的,与具体平台相关,可以调用is_lock_free接口进行查询。
2.thread详解
3.mutex详解
4.future详解
5.conditon_variable详解
6.atomic详解
c++ atomic库和atomic_flag库
CAS——Compare-and-swap
7.内存模型
non-blocking algorithm
c++ 内存模型
Memory Barriers: a Hardware View for Software Hackers