主要是前6章的内容
[TOC]
关于必发的基础
1. 为什么出现并行计算
摩尔定律在CPU的计算性能上的失效,使得从2005年开始不再追求单核的计算能力,关注于研究如何将多个独立的计算单元整合到单独的CPU中,就是所说的多核CPU。
摩尔定律内容为:每18个月到24个月,我们计算机性能能翻一番。
这个定律有效性超过半个世纪,在2004年之后遇到了障碍,因为制造工艺已经精确到了纳米级别。
虽然并行程序的设计个实现异常复杂,但是在图像处理和服务端程序中需要使用并行技术的,前者需要极大的计算量,特别是矩阵的计算,后者一方面是需要承受很大的用户访问量,一方面拥有更加复杂的业务模型。所以软件开发者必须学习之。
2. 同步与异步?并发与并行?临界区?阻塞与非阻塞?死锁饥饿活锁?
同步相当于在商店买冰箱,异步相当于网购冰箱。同步与异步通常用来形容一次方法调用,同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的操作。异步调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者可以继续后续的操作,而异步调用会在另一个线程中真实执行。整个过程中,不会阻碍调用者的工作,对于调用来说,异步调用似乎是一瞬间完成的。
并发与并行都可以表示两个或者多个任务一起执行,但是侧重点有所不同,前者偏重于多个任务交替执行,而多个任务之间有可能还是串行的,并行是真正意义上的同时执行。实际上,如果系统内只有一个CPU,那么使用多进程和多线程任务,这些任务不可能是真实并行的,毕竟一个CPU只能执行一条指令,在这种情况下多进程或者多线程就是并发的,不是并行的,并行只可能出现在多核CPU中。
临界区用来表示一种公共资源或者说共享数据。每一次,只有一个线程可以使用它,一旦临界区资源被占用,其他线程要使用的话必须先等待
阻塞与非阻塞通常用来形容多线程的相互影响
饥饿指的是一个线程或者多个因为种种原因无法获得所需要的资源,导致一直无法执行,活锁指的是线程之间互相主动释放资源给对象,导致资源不断地在两个线程之间跳动,没有一个线程可以同时拿到所有资源正常执行
3. 并发级别有哪些?
由于临界区的存在,多线程之间的并发必须受到控制,根据控制并发的策略,可以把并发的级别分为阻塞,无饥饿,无障碍,无锁,无等待
4. 加速比以及两个定律结论
加速比为优化前系统耗时/优化后系统耗时
为了提高系统的速度,仅增加CPU处理器的数量并不一定能起到有效的作用,需要从根本上修改串行行为,提高并行化的模块比重,在此基础上合理的增加并行处理器数量,以最小的投入,得到最大的加速比。
如果可并行的代码所占的比例足够大,那么加速比就能随着CPU的数量线性增长
5. java内存模型JMM
产生的原因为定义一种规则,保证多个线程之间可以有效得正确地协同工作
- 原子性:一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
- 可见性:一个线程修改了某个共享变量的值后。其他线程是否能够立即知道这个修改
- 有序性:程序执行时可能会进行指令重排,重排后的指令与原指令的顺序未必一致(指令重排可以保证串行语义一致,但是没有义务保证多线程间的语义也一致)一条指令的执行可以分为很多步骤,工程师发明了流水线技术来执行指令,有了流水线,CPU才能真正高效地执行,但是流水线害怕被中断,耗时长,怎么解决了,指令重排,这样就提高了CPU处理性能,确实带来了乱序的问题,但是这点牺牲是完全值得的
- 哪些指令不能重排:happen-before规则
java并行程序的规则
1.线程与进程的含义?
简单来说,电脑中.exe文件被加载后就是一个进程,进程是一个容器,里面有一个或者多个线程,线程之间可以协调工作也可能资源竞争。稍微专业的术语说就是,线程是轻量级的进程,是程序执行的最小单元,使用多线程而不是多进程取进行并发程序的设计,因为线程间的切换和调度的成本远远小于进程
2. 线程的初始化操作
包括新建一个线程,终止线程,线程中断,等待和通知,挂起和继续执行线程,等待线程结束和谦让
3. volatile关键字
当你用volatile声明一个变量时,就等于告诉虚拟机,这个变量极有可能会被某些程序或者线程修改,为了确保这个变量被修改后,应用程序范围内的所有线程都能够看到这个改动,虚拟机就改用特殊的手段,保证了这个变量的可见性等特点。
volatile关键字不能替代锁,它无法保证一些复合操作的原子性,它能保证数据的可见性和有序性
4. 分门别类的管理;线程组
在一个系统中,如果线程的数量很多,而且功能分配很明确,就可以把相同功能的线程放置在同一个线程组里面
5. 守护线程
守护线程是一种特殊的线程,他是系统的守护者,在后台默默地完成一些系统性地服务,比如垃圾回收线程
设置守护线程必须在线程启动之前设置
6. 线程优先级
优先级高的线程在竞争资源时会更加有优势,当然这是一个概率问题
7. synchronized关键字
并行程序开发的一个关注重点就是线程安全问题,高效率不能以牺牲正确性为代价
关键字synchronized有很多种用法,指定加锁对象,直接作用于实例方法,直接作用于静态方法
synchronized除了用于线程同步,确保线程安全外,还可以保证线程间的可见性和有序性
8. 隐蔽的错误
修复BUG是程序员日常的工作之一,如果程序出现错误,你看到了异常堆栈或者日志,应该感到开心,最怕的就是系统没有任何异常表现