Go并发
并发编程概念
关键词
-
串行程序
: 串行程序特指只能被顺序执行
的指令列表 -
并发程序
: 可以被并发执行
的两个及以上
的串行程序的综合体 -
并行程序
: 被设计成可以在并行硬件
上执行的并发程序 -
分布式系统
等于并行系统
等于并发系统
进程
进程
: 一个程序的执行称为一个进程。进程是操作系统进行资源分配的一个基本单位
进程的衍生
由父进程使用系统函数fork,fork出一个子进程。子进程获得父进程的数据段,堆和栈的副本。
扩展:Linux写时拷贝技术
进程的标识 进程的ID(PID
) 当前进程的父进程ID(PPID
)
进程的状态: 操作系统之进程的几种状态
进程空间:用户空间
内核空间
系统调用
: 为了使用户进程能够使用操作系统更底层的功能,内核会暴露出一些接口供他们使用,这些接口是用户进程使用内核功能的唯一手段
。系统调用时向内核空间发出一个明确的请求
内核态
和 用户态
用户态
: CPU只能对用户空间进行访问内核态
: 控制计算机的硬件资源
实现
: 当用户进程发出一个系统调用时,内核
会把CPU从用户态切换
到内核态,而后会让CPU执行对应的内核函数
进程间的上下文切换
: 凭借CPU的威力快速地在多个进程之间进行切换
进程间通信 IPC
-
管道
: 一种半双工(单向)的通信方式,只能用于父进程与子进程以及同祖先的子进程之间的通信 -
信号
: 用来通知接收进程某个事件已经发生 -
套接字
: 可用于不同机器之间的进程间通信 扩展 :RPC远程过程调用 -
共享内存
: 最快的IPC
方式,多个进程共享同样的资源。为了做到这一点,需要内核提供锁
和同步机制
竞态
: 多个进程对一个资源进行访问原子操作
: 执行过程中不能被中断
的操作(所有的系统调用都属于原子操作)临界区
: 只能被串行化
访问或执行的某个资源或某段代码称为临界区互斥
: 保证只有一个
进程或线程在临界区之内的做法
线程
线程
: 线程可以视为线程的控制流,一个进程至少会包括一个线程线程标识
: 由操作系统内核分配和维护
线程控制的系统调用:
- 创建线程
pthread_create
- 终止线程
pthread_cancel
- 连接已终止的线程
pthread_join
- 分离线程
pthread_detach
线程实现模型
- 用户级线程模型
- 内核级线程模型
- 混合型线程模型
内核调度实体 (Kernel Scheduling Entity)
用户级线程模型
线程是由用户的线程库全权管理,所有的调度和管理都是用户级程序的自主行为。(现代操作系统都不适用这种模型来实现线程)
内核级线程模型
由内核复制管理,属于内核的一部分。会给内核的调度器造成非常大的负担。
缺点 : 资源消耗较大,调度速度较慢等。但与用户级线程模型相比有较大优势。(很多现代操作系统都是由以内核级线程模型实现线程)
混合型线程模型
混合型线程模型的线程库会通过操作系统内核创建多个内核级线程,然后,通过内核级线程对应用程序进行调度。大多数此类线程库都可以将这些应用程序动态地与内核级程序关联。因为混合型线程模型实现的复制性,它往往不会是操作系统内核的开发者所采用。但是,这种模型可以很好地在编程语言层面上实现并充分发挥其应有的作用
扩展 : 线程的3种实现方式
线程的同步
关键点是解决共享数据的一致性
互斥量
条件变量
原子操作
不当的互斥量导致的死锁问题
例如 : 两个互斥量的临界区重叠
解决方案
- 试锁定-回退
- 固定顺序锁定
(A为先锁定X再锁定Y,B为先锁定Y再锁定X。改成A先锁定Y再锁定X)
条件变量
: 条件变量是对应的共享数据的状态改变时,通知其他因此而被阻塞
的线程。条件变量总是
和互斥量组合使用
多线程还是多进程?
多线程作为更加现代的并发编程方式在系统资源的利用和程序性能的提高方面都更加有优势。但是,在某些情况下。比如对信号的处理
,同时运行多套不同的程序
以及包括多个需要超大内存支持
的任务等,传统的多进程编程方式可能会更加适合。
临界区的设计建议
- 控制临界区的纯度
- 控制临界区的粒度
- 减少临界区代码的执行耗时
- 避免长时间持有互斥量
- 优先是有原子操作而不是互斥量
有疑问加站长微信联系(非本文作者)