并发与并行的区别
并发是指多个线程操作同一个资源,不是同时执行,而是交替执行。单核CPU,只不过因为CPU的时间片很短,速度太快,看起来是同时执行。
并行才是真正的同时执行,多核CPU。每个线程使用一个单独的CPU的资源来运行。
并发示意图:
并行示意图:
但在多数情况下,我们的即使有多核,也同样存在并行的情况,且存在并行与并发同时存在的情况。
并发概念
Java并发的重要性毋庸置疑,可以最大化的提高计算资源的效率。
并发是多线程交替的访问同一个资源,该资源本身的特点是同一时刻只允许一个线程的访问,那么就存在竞争的问题。同一个资源可以是CPU资源,也可以是内存资源。
临界资源和临界区
临界资源:一般指内存资源,一个时刻只允许一个进程(在java中,是线程)访问,一个线程正在使用临界资源的时候,另一个线程不能使用。临界资源是非可剥夺性资源,即使是操作系统(或JVM)也无法阻止这种资源的独享行为。
临界区:是一种线程中访问临界资源的那段程序代码。(注意:是程序代码,不是内存资源了,这就是临界资源与临界区的区别)。
我们规定临界区的使用原则(也即同步机制应遵循的准则):“空闲让进,忙则等待,有限等待,让权等待”,分别来解释一下:
- 空闲让进:临界资源空闲时一定要让进程进入,不发生“互斥礼让”行为。
- 忙则等待:临界资源正在使用时外面的进程等待。
- 有限等待:进程等待进入临界区的时间是有限的,不会发生“饿死”的情况。
- 让权等待:进程等待进入临界区是应该放弃CPU的使用。
什么是线程安全?
如果一个操作序列,不考虑耗时和资源消耗,在单线程执行和多线程执行的情况下,最终得到的结果永远是相同的,则这个操作序列叫做线程安全的。如果存在不相同的概率,则就是非线程安全的。
并发的特性
Java并发模型是围绕并发过程中如何处理原子性、可见性、有序性3个特征设计。因此特性有以下三种:
原子性
原子性:如果一个操作时不可分割的,那就是一个原子操作,也叫这个操作具有原子性。相反的,一个操作时可以分割的(如a++,它实际上是a=a+1),则就是非原子操作;原子操作是线程安全的,非原子操作都是非线程安全的,但是我们可以通过同步技术(lock)或同步数据模型(Concurrent容器等)把非原子操作序列变成线程安全的原子操作。
可见性
可见性:一个变量被多个线程共享,如果一个线程修改了这个变量的值,其它线程能够立即得知这个修改,则我们称这个修改具有可见性。
有序性
Java线程的有序性,表现为两个方面:
- 在一个线程内部观察,所有操作都是有序的,所有指令按照“串行(as-if-serial,字面意思是“像排了序一样”,as-if-serial的真正含义是不管怎么重排序,一个单线程程序的执行结果都必须相同)” 的方式执行。
- 在线程间观察,也就是从某个线程观察另一个线程,则所有其他线程都可以交叉并行执行,是正序的,唯一例外的是被同步方法、同步块、volatile等字段修饰的强制同步的代码,需要在线程间保持有序。
更多关于Java多线程的内容,详戳【Java多线程】,其他内容,详戳主页。