Java高并发设计-----走进并行世界-----1
走进并行世界
1.1何去何从的并行计算
1.1.2摩尔定律
Linus Torvalds:Linux大佬:并行计算智能在图像处理和服务端编程两个领域使用,并且它在着两个领域有着广泛的使用,但是在其它任何地方,并行计算毫无建树!
概念:硬件每18个月性能翻一倍
很显然没有办到!!!
所以只能软件来凑了
1.2必须知道的几个概念
1.2.1同步和异步
同步:只有执行完前一步,才能进行接下来的操作
异步:调用方法后直接返回,随后执行接下来的步骤。不需要等待调用的方法产生结果。被调用的方法通常在另外一个线程上执行。整个过程不会阻碍调用者继续后续的操作
1.2.2并发(Concurrency)和并行(Parallelism)
并发:CPU高速的切换,以至于觉的两个线程在一起执行
并行:真实的两个线程同时执行
1.2.3临界区
多线程使用的共享资源,但是每一次只能有一个线程使用它,一旦临界区资源被占用,其它线程必须等待前一个线程执行完成之后才能占有。
1.2.4阻塞(Blocking)和非阻塞(Non-Blocking)
阻塞:线程因为临界区资源产生了等待
非阻塞:不用等待(具体概念,日后补充)
1.2.5死锁(Deadlock)、饥饿(Starvation)、活锁(Livelock)
死锁:例如有两个妹子x和y,A占有x,B占有y;但是A不想抛弃x的情况下得到y,B不想抛弃y的情况下得到x;所以AB两个老渣男尬住了,争执不下。
饥饿:好理解为,老备胎了,CPU一直就是不执行它,它一直等待。
活锁:线程A需要资源x,线程B需要资源x;A、B同时觉得你让给你吧,结果A、B同时礼让了,然后谁都没得到;然后A、B又同时要x,结果又都礼让了。
1.3并发级别
应该是指并发的程度吧,不知道这个是衡量什么的
1.3.1阻塞
为了资源,互相等待;用锁就会产生等待
1.3.2无饥饿
提交的线程一定能被执行,不会不执行
1.3.3无障碍
每个线程都可以肆无忌惮的获得临界区资源
无障碍:一种乐观的策略,任务线程不会发生冲突。
策略:一致性标记-----------将公共资源标记,操作前,先读取并保存标记,操作完成后,再次读取,检查标记是否修改,如果一致,就说明资源访问没有冲突。如果不一致,就重试;每个线程修改数据都会修改标记。
1.3.4无锁
所有线程对临界区进行访问,所有线程都无限循环的修改数据,直到一个修改成功,然后退出。说实话不懂!
1.3.5无等待
在无锁的基础上,增加一个在有限步的基础上内完成线程任务
1.4并行重要定律
1.4.1Amdahl定律
1.4.2Gustafson定律
1.5JMM
Java内存模型(JMM)-----现在还不是很了解
1.5.1原子性
原子性:指一个操作是不可终端的
1.5.2可见性
一个线程修改了某一个共享变量的值时,其它线程能够立即了解到这个修改
1.5.3有序性
有序性:要保证一些代码执行必须在另外一些代码前面
一般情况下有序,但是有时候会发生指令重排
指令重排:保证了串行语义的一致,但是没有保证多线程间的语义一致性
为什么会发生指令重排:
因为CPU采用的是流水线执行,所以Java虚拟机和执行系统会对指令进行一定的重排,来满足流水线执行!!!自己想想就明白咯,阿喆!!!
1.5.4哪些指令不会重排:Happen-Before规则
- 程序顺序规则:一个线程内保证语义的串行性。
- volatile规则:volatile变量的写先于读发生
- 锁规则:解锁一定在加锁之前。
- 传递性:A先于B,B先于C,那么A势必先于C
- 线程的start()方法先于它的每一个动作
- 线程的所有操作先于线程的终结(Thread.join())
- 线程的中断(interrupt())先于被中断线程的代码。
- 对象的构造函数的执行、结束先于finalize()方法