本文是Java并发系列的开篇,主要讲一些并发的计算机基础知识。本系列所讲的知识框架也是基于《Java并发编程的艺术》一书,所讲的内容也多围绕于并发concurrent包下的类。
正文
并发的前提是多线程间的协同运作,如果是程序是单线程运作并发也无从谈起。那么首先要理解两个问题。
什么是进程、线程?
答:进程是程序的运行过程,有内存空间、CPU运行时间、IO设备,进程是系统进行资源分配和调度的一个独立单位。
线程是CPU独立运行和独立调度的基本单位,一个进程里可以拥有多个线程,进程空间包括不同线程可共同访问的公共空间和私有空间。
Java开启多线程的方式?
1、装配runnable接口,重写run()方法。
2、继承Thread类,重写它的Start方法。
Java线程状态?
Java线程间的协作方式?
显然,不进行协作的多线程它们的作用要大打折扣,而线程协作关注的两个重要问题是Java线程间如何进行通信以及线程间如何进行同步?
Java采用的共享内存模型,线程间通过正确同步和读写共享内存数据达到线程通信和同步的目的,当然要正确的读写共享内存绝不是容易的事情,它包括了很多并发知识。但我们现在只要建立这种认知就够了。
Java间有以下协作的方式:1、等待通知机制(Synchronized和object配合、Lock和Condition配合)
2、volatile
3、synchronized
4、管道流
它们直接的详细内容会在后文讲到。
为什么会出现并发结果不一致问题?
为什么没有正确编写程序会引发并发问题?这跟计算机底层运行机制有关。
1、重排序问题(重排序为了提高程序运行效率),Java重排需只保证了单线程的结果一致性,没有保证多线程结果一致性,保证多线程结果一致性的是happens-before规则。重排序包括编译器重排序、指令集重排序、CPU重排序,它们都会让多线程出现并发问题。
2缓存问题,首先Java线程通信是采用共享内存的方式通信,A线程将数据写入主内存,B线程从主内存读取数据以达到通信目的。系统为了提高效率建立了缓存,它导致了线程和共享内存间的通信并不是即时的,所以会出现并发问题。
Java本身也只是保证了as-if-serial语言,即保证单线程程序运算结果不会改变。而对于多线程结果不改变的语义happens-before语义则只保证正确同步的程序结果不变。
Java保证并发Volatile、Sychronized关键字和CAS操作起到了关键作用,它们的知识点在下篇文章: