主内存与工作内存
主内存中存放了所有的变量,这个变量的概念不同于java中的变量,这里的变量是指实例变量、静态
变量和构成数组对象的元素。每个线程都有工作内存,线程在使用变量时,不能直接操作主内存中的变量,
而只能操作其在工作内存中的拷贝。
主内存和工作内存上有八个操作。lock和unlock操作中,unlock发生时,Java内存模型要求工作内存
重新获取在工作内存中的变量拷贝的值。
volatile
volatile是java多线程中最轻量级的同步机制,volatile保证一个变量在内存中只有一份拷贝。
一个变量在被volatile修饰以后,它具有两个特性:
1. 在线程A修改了volatile变量后,所有共享该变量的线程都会得到该变量的变化。因为java内存模型
强制要求volatile变量在use之前必须要从主内存中重新获取该变量的最新值,在assign只有必须重新写会主内存。
2. 禁止指令的重排序。普通的变量不能保证赋值操作的顺序和程序代码中的执行顺序一样。volatile提供的内存屏障机制可以有效的解决在线程内指令重排序导致的代码执行顺序问题。指令重排序是指CPU
采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理。
volatile关键字的性能消耗小于同步关键字和锁。
要使用volatile进行有效同步的两个条件:
1. 运行结果不依赖当前值或能够保证只有单一线程对其进行修改。
2. 变量不需要其他状态变量共同参与构成不变约束。比如start和end变量都被声明为volatile,并且start和end组成不变约束start
原子性、可见性与有序性
这三个性质在Java内存模型中都有清晰的体现。
原子性:
通过read、load、use、assign、store、write操作来体现,可以说基本数据的读写都是原子的。
可见性(一个线程修改了共享变量的值,其他线程能够立即得知这个修改):
通过强制要求的操作执行顺序来体现。
有序性:
如果在本线程中观察,所有的操作都是有序的,如果在一个线程中观察其他线程,所有的操作都是
无序的,前半句是指“线程内表现为串行的语义”,后半句是指“重排序指令”和“主内存变量和工作内存的不同步”
线程的实现
- 内核线程
用户程序不直接调用KLT(kernel-level thread)而是使用内核线程的一种高级接口——轻量级进程
(Light Weight Process,LWP)。 - 用户线程
由程序在用户态实现的线程。 - 内核线程与用户线程结合
线程可以由程序创建,节省了开销,又能通过PWL享用操作系统的调度功能和处理器映射。 - Java的线程实现
Java在jdk1.2之前是基于称为“绿色通道”的用户线程来实现的,1.2之后通过内核线程来实现。Java线程
有十种优先级。