并发编程之始

从今天开始看《并发编程的艺术》,然后留下学习的笔记,是学习,是提问,是散发思维,是形成自己的知识体系。抱着学习研究的态度,去学习这本书,去深挖一门技术。看完一遍,还有一遍,如此反复。发布出来是因为,技术需要交流,如果我有写错的地方,希望朋友们可以狠狠批评,我认真改过。好,废话不多说,马上开始头脑风暴。

上下文切换,时间片,线程调度算法

1 什么是上下文切换,上下文切换的原理是什么?

1.1 cpu调度算法干了什么?

在操作系统层面,有一个概念叫模式切换,从用户态到内核态,或者从内核态到用户态。一般上下文切换指的是进程上下文切换,或者线程上下文切换。因为进程运行过程当中,会产生,局部变量,进程的方法栈,当cpu调度系统,从一个时间片切换到另一个有效的时间片时,会保存现场数据(上下文数据),局部变量表,程序运行到哪一行,进入PC(程序计数器)等一些数据到内核进程的堆栈中。 实际上,是因为cpu内部有一个计数器,当计数器倒计时到0,那么代表时间片用完了,这个时候,会产生一个中断去触发,cpu调度算法,去重新分配时间片给在就绪队列中的进程。如此循环往复。

1.2 CPU内部的MMU干了什么?
1.2.1首先MMU的主要功能是什么?
  • 地址转换
  • 权限管理
  • 交换分区
    首先引入两个概念,虚拟地址(VA)和物理地址(Virtual Address , Physical Address)。如果处理器没有MMU,或者有MMU但没有启用,CPU执行单元发出的内存地址将直接传到芯片引脚上,被内存芯片(以下称为物理内存,以便与虚拟内存区分)接收,这称为物理地址(Physical Address,以下简称PA)如果处理器启用了MMU,CPU执行单元发出的虚拟地址将被MMU映射转换成PA。那么中间肯定有一个像对照表一样的东西,从VA到PA。如果是32位处理器,那么他的地址总线是32位的,那么代表他的寻址能力是4G。但是实际上,这个表是存在于CPU内部一个叫TLB(Translation Lookaside Buffer 一般叫页表缓存,这个是页表缓存,就有命中hit和miss,在物理内存的内核区域还有完整的页表)结构如下图所示:
    image.png

那么他不可能是这么大的一个表,肯定空间不够。那他如何寻址?
答案是通过将内存分页。通过页帧号+页内偏移来寻址,一般32位处理器是一页32KB。寻址方式 如下图。

image.png

然后回到原先的问题,MMU干了什么?在进程切换的时候,这里他要清空一些TLB中的映射条目,因为从一个虚拟地址空间到另外一个地址空间。有些条目,已经失效了。但是内核进程由于被用户进程锁共享,一直在内存的某个区域不动,所以这部分的话,不需要刷新。cpu缓存中的数据,也要被清空,设置为invaliad。这就导致,进程切换的时候,很多东西都是未命中,需要重新加载。切换时图片如下所示:


image.png

2 疑问?

什么时候会触发上下文切换? (这里的疑问??)是和进程一样的吧,时间片到了我的猜测,只有在系统时钟周期到了,或者由于中断,陷入内核态,才会触发调度算法。
《并发编程的艺术》书中显示:
多线程竞争锁时,会引起上下文切换

3 如何减少上下文切换

  • CAS,无锁并发编程。
  • CLH 队列,采用唤醒传递机制 ,避免大量线程同时唤醒,引起一个惊群效应
  • 分段锁,或者锁的离散化 ,就像jdk1.7 的ConcurrentHashMap .采用更强的离散函数。
  • 在一定量的任务前提下,合理使用线程池。使得在用的线程得到更大程度的利用。比如工作窃取fork/join ,线程的重复利用。虽然说本身并不能减少上下文切换,但是参数上下文切换的线程少了,那就间接的减少了上下文切换。
  • 协程。

3.1 协程是什么?

线程不同状态之间的转化是谁来实现的呢?是JVM吗?
并不是。JVM需要通过操作系统内核中的TCB(Thread Control Block)模块来改变线程的状态,这一过程需要耗费一定的CPU资源。
多线程编程的耗性能操作:

  • 同步锁
  • 线程的状态切换
  • 线程的上下文切换
    但是,协程大大减少了上面所涉及的性能消耗。
    协程,英文Coroutines,是一种比线程更加轻量级的存在。
    协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。
    这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。

3.2 协程的应用

  • Python语言
    python可以通过 yield/send 的方式实现协程。在python 3.5以后,async/await 成为了更好的替代方案。
  • Go语言
    Go语言对协程的实现非常强大而简洁,可以轻松创建成百上千个协程并发执行。

你可能感兴趣的:(并发编程之始)