任务调度
进程让操作系统实现了并发,而线程让进程内部实现了并发
线程安全的本质
(1) 原子性
(2) 有序行 —> 编译器的重排序和CPU的指令重排序
(3) 可见性 —> 一个线程对共享变量的修改对另外一个线程不可见
线程的状态及状态的切换
6种状态
- new
- runnable(就绪、运行)
- blocked(阻塞)
(a) 等待阻塞
(b) 同步阻塞
© 其它阻塞 - (4) waiting
- (5) time waiting
- (6) terminated
如何中断一个线程
interrupt(中断) —> 会使线程抛出 InterruptException中断异常
isInterrupt()方法判断是否被中断
Thread.interrupted(); //复位,之后isInterrupt()方法将变为false
volatile原理
-
概述
-
并发编程中的三个概念:
- 原子性:即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
- 可见性:可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
- 有序性:即程序执行的顺序按照代码的先后顺序执行。
-
volatile 可以保证可见性、防止指令重排序(解决了可见性、有序性问题)
-
synchronized 解决了原子性、可见性、有序性问题
-
volatile/synchronized —> Lock指令
- 把当前处理器缓存行的数据写回系统内存
- 使得CPU内的缓存地址失效
-
-
CPU 级别的缓存一致性原理
为了解决缓存一致性问题CPU通过两种锁的途径来解决: 总线锁和缓存锁
缓存一致性LOCK- 总线锁(全局锁)
是指变量从共享内存获取到某颗CPU独有内存后,其它CPU核心再次获取时会被阻塞住,直到释放锁(相当于悲观锁)性能比较低,现代CPU架构绝大多数都是用缓存锁的方式来实现的 - 缓存锁(锁定缓存行)
X86架构 MESI协议(缓存一致性协议)
简写 英文 中文 M modified 修改 E exclusive 独占 S Shared 共享 I Invalid 失效 (1) 读取count变量到缓存中,我们认为当前状态是Share
(2)当其中一个CPU核心修改了count值,状态会先变成独占E
- 设置成E(独占)使得其它核心中的线程获取count值时,获取不到
- 设置成M后对数据做修改,修改后通过嗅探协议通知其它CPU核心缓存的count值失效,并将count值由CPU核心写回主内存
- 另外一个CPU核心接到count缓存失效的通知后,将状态变为I (invalid),再次从主内存重新获取count值
- 总线锁(全局锁)
-
指令重排序问题
指令重排序不会影响单个线程的执行,但是会影响到线程并发执行的正确性。
- 内存屏障
(1) 是CPU或者编译器对内存的一个随机访问操作的同步点
(2) 就是在两个操作中间加了一个屏障(或者说同步的点),该屏障之前所有的指令全部执行完毕, 屏障之后的指令能够读取到屏障前指令的结果 - 内存屏障有三种
(a) store barrier //写屏障
(b) load barrier //读屏障
(c ) full barrier //全屏障 —> 具有写屏障和读屏障的功能(综合体) - 内存屏障的作用
(1) 保证可见性
(2) 保证有序性
内存屏障是CPU层面的东西,Java无法直接触及,Java通过JMM来间接触及内存屏障
- 内存屏障
-
JMM规范
Java Memory Model —> Java内存模型
定义的是线程和内存的交互方式
-
volatile的代码使用
join原理
在很多情况下,主线程创建并启动了线程,如果子线程中要进行大量耗时运算,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了。方法join()的作用是等待线程对象销毁。这里有一个很值得注意的问题,join的底层调用的是wait方法,而且是循环调用,源码如图所示:
我们可以看到源码中join方法会在while循环中一直调用wait方法,假如wait的时间是1000ms,在500ms的时候另外一个线程调用了notifyAll方法时,线程就会苏醒。
更多详情请见
https://blog.csdn.net/madongyu1259892936/article/details/79230924 线程基础-volatile关键字
https://www.cnblogs.com/yanlong300/p/8986041.html 并发研究之CPU缓存一致性协议(MESI)
https://blog.csdn.net/beiyetengqing/article/details/49580559 多线程之指令重排序