目录

并发编程模型中的两种基本模型是消息传递(message passing)和共享内存(shared memory)。

  1. 消息传递模型:在消息传递模型中,并发执行的进程通过发送和接收消息来进行通信。每个进程都有自己的地址空间,且彼此独立。进程之间通过发送消息来交换数据,并通过接收消息来处理接收到的数据。消息传递模型可以通过显式地发送和接收消息来实现进程之间的同步和互斥。
  2. 共享内存模型:在共享内存模型中,多个进程可以同时访问相同的共享内存区域。进程可以读取和写入共享内存中的数据,这些操作可以被其他进程立即看到。进程之间通过对共享内存的操作来进行通信和同步。这种模型通常使用锁机制等同步原语来确保共享内存的一致性和正确性。

这两种模型各有优缺点:

  • 消息传递模型更容易实现进程之间的隔离和灵活性,因为每个进程都有自己的地址空间。但是,在大规模分布式系统中,消息传递可能会引入较高的开销。
  • 共享内存模型可以提供更高的性能和效率,因为进程可以直接访问共享内存而无需通过消息传递的开销。但是,共享内存模型需要谨慎处理并发访问和数据一致性的问题。

虚假唤醒(spurious wakeup)

多线程与IO

死锁典型案例

线程基础操作

转移线程归属权

实现joinning_thread

获取线程id

线程间共享数据

互斥锁的实现通常包含两个基本原理:
1、提供线程间自动的状态转换
2、保障了互斥锁操作期间,所操作的变量的内存和临界区外进行隔离

对于mutex重复加锁会产生什么影响

使用mutex保护链表操作

实现线程安全的栈容器

lock锁多个mutex

每次一个锁,比较拷贝值

避免死锁

实现层级互斥锁

unique_lock使用

初始化过程中保护共享数据的几个方法

保护读多写少的数据结构

递归加锁std::recursive_mutex使用

避免使用recursive mutex

主要就是condition variable、future、latch、barrier的使用

条件变量等待条件成立

假定某个线程按计划仅仅等待一次,只要条件成立一次,它就不会再理会条件变量,那么此时用future更好。

future等待一次性事件发生

std::promise结合future编程

限时等待

通信式串行进程(communicating sequential process,CSP)

latch、barrier(todo)

C++原子操作以及内存模型

原子类型变量的赋值操作符不返回引用,而是按值返回

2.memory_order_consume(在 C++17 中弃用)保证在依赖于原子变量的特定操作之间保持顺序。但是,由于其复杂性和实现的困难,它在 C++17 中已被弃用。

4.memory_order_release:防止操作在原子操作之后进行重排。所有在原子操作之后的读或写操作都不会被重排到原子操作之前。

6.memory_order_seq_cst:提供最严格的内存顺序保证。所有的 memory_order_seq_cst 操作在单个程序中看起来就像是按照某种顺序执行一样,即这些操作是顺序一致的。几乎所有的原子操作默认都是 memory_order_seq_cst,这也是最安全、最直观,但可能是效率最低的选项。

判断atomic是否lock free

std::atomic_flag使用

std::atomic<T *>算术形式指针运算

对于浮点数类型的算术原子运算并不存在,因为根据IEEE754浮点数的标准,可以采用不同的标准表示同一个数值。虽然参与比较的两个值相等,但是比较-交换操作还是会因为表示方式不同而失败。

shared_ptr线程安全

(一致性模型)四种一致性

memory_order简单阐述

实操

基于锁的并发数据结构设计

设计并发数据结构时,可以使用多线程中的构建块,比如:互斥量和条件变量。当然,也要保证构建块在并发环境下的线程安全。

减少保护区域,减少串行化操作,提升并发访问的能力

并发数据结构设计指南

设计一个线程安全的队列(1.1)

设计一个线程安全的队列(1.2)