我理解的Java并发基础(一):一些基本概念

1,什么是并发?
  在cpu角度讲,多个cpu的核同时在工作。从Java的角度将,JVM在同一时刻在处理多个线程的请求。

2,为什么要并发?
  并发适用于多核处理器,以解决单线程阻塞导致效率低的问题,尽可能利用cpu空闲等待时间。

  缺点:线程间的切换具有额外开销。(用户线程的上下文要复制到cpu线程上来执行)

3,cpu、进程、线程的关系
  cpu:执行计算机指令
  操作系统的进程:程序的一次执行
  操作系统的线程:操作系统调度器的调度的基本单位,交由cpu执行
  cpu的线程:存放要执行的数据、指令等,是cpu的基本执行单位

  处理器的线程,与操作系统的进程,是 N:N 的关系。
  操作系统的进程,与操作系统的线程,是1:N的关系。
  所以,处理器线程与操作系统线程之间是 N:N 的关系。
  一个进程至少有一个线程。线程不能跨域进程与访问另一个进程的内容。

备注:
  通常cpu的线程和核心数对应,几核就是几线程。但是单个线程并不能让单个cpu核满载造成cpu浪费,于是有了超线程技术,即一个cpu核负责两个或多个线程的运行。

4,多线程的使用方式
  多线程的使用有两种:协同式和抢占式。
  协同式的实现比较简单,由于是在当前线程主动触发其他线程并等待结果返回,对调用者来说是可以感知的,不存在线程安全问题。缺点是等待的过程是阻塞的,线程阻塞会造成一定程度的浪费性能。比如Lua。而Java采用抢占式。

5,多线程争夺cpu使用权
  cpu的基本调度单位是线程,由一个叫做“调度器(scheduler)”的操作系统的组件来调度。cpu的核会在一个 时间片 内执行用户线程的操作。调度器会根据线程的优先级和线程的饥饿程度(等待时间)两个因素来调度线程。

6,Java的线程与进程
  jvm的线程与进程,是对操作系统的线程与进程的一种封装,方便操作。

  jvm将操作系统的进程,封装为Process(抽象类),唯一实现类是ProcessImpl。有创建工具类ProcessBuilder。jvm对进程的封装提供非常少的api,因为制定者不主张在java中以创建进程的方式执行多任务。

  jvm将操作系统的线程,封装为Runable接口,java.lang包下有两个实现类,Thread和Shutdown。Shutdown是用来执行JVM关闭的时候的钩子函数的。普通代码实际运行的时候,需要一个Thread类的对象来.start()来执行。这个.start()是一个synchronized方法,方法内部会调用native的.start0()交给操作执行。Thread类还提供很多native的方法来供调用。

  java.concurrent包下有Callable接口,可以有返回值(Future模式)。

7,线程的缓存与一致性规范
  计算机的cpu的运算速度与内存的读写速度相差好几个数量级,因此引入了高速缓存。每个cpu的线程单独配一个高速缓存。
  带来的问题:缓存一致性(CacheCoherence)。为了解决缓存一致性的问题,要求各个处理器访问缓存时遵循一定的协议(比如:MESI协议)。
  Java虚拟机有自己的内存模型,虚拟机通过操作系统可以操作cpu的线程和高速缓存,所以Java内存模型定义了如何解决缓存一致性的规范。

8,线程间的数据通讯
  协同式天然具备线程间的通讯能力。Java采用抢占式,线程只与主内存交互。如果线程间需要通讯的话,需要先将数据从线程自己的工作内存写回到主内存,另外一个线程再从主内容加载到它的线程。
  每一个java线程拥有自己的工作内存,所有的java线程共用一个主内存。

方便理解:
  主内存对应java堆中的对象实例数据部分,物理硬件的主内存。
  工作内存对应虚拟机栈中的部分区域,程序运行时主要访问读写的是工作内存。
  这种理解是片面的不准确的,但刚接触的时候比较容易理解一些。

参考资料:

猜你喜欢

转载自my.oschina.net/u/3466682/blog/1617805