多线程环境:
一个进程包含多个线程。
多个线程同时读写一个对象,成员变量,就会产生问题,这就是多线程环境。
JVM内存模型:
http://gityuan.com/2016/01/09/java-memory/
(1)线程私有区
程序计数器,记录正在执行的虚拟机字节码的地址;
虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;
本地方法栈:虚拟机的Native方法执行的内存区;
(2)线程共享区:
Java堆:对象分配内存的区域;
方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据;
常量池:存放编译器生成的各种字面量和符号引用,是方法区的一部分。
内存可见行问题
线程私有区不会有内存可见行问题。
内存可见行问题发生在线程共享区:
何为内存可见行问题:
http://www.infoq.com/cn/articles/java-memory-model-1
解决方案:
1)volatile关键字
volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。
volatile的适用范围:
https://blog.csdn.net/yueliangniao1/article/details/7227803
上面的代码将n=n+1改成了inc(),
* 其中inc方法使用了synchronized关键字进行方法同步。
* 因此,在使用volatile关键字时要慎重,
* 并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原子操作,
* 当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,
* 只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,
* 这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,
* 可以使用synchronized来代替volatile。
2)原子基本数据类型
https://juejin.im/entry/5a9b93f3f265da23741070ca
AtomicBoolean、AtomicInteger、AtomicLong,
指令重排序
多核处理器并行并行执行;
解决方案:
happens-before原则
http://www.infoq.com/cn/articles/java-memory-model-1
程序顺序规则:一个线程中的每个操作,happens- before 于该线程中的任意后续操作。
监视器锁规则:对一个监视器锁的解锁,happens- before 于随后对这个监视器锁的加锁。
volatile变量规则:对一个volatile域的写,happens- before 于任意后续对这个volatile域的读。
传递性:如果A happens- before B,且B happens- before C,那么A happens- before C。
Java线程状态分析
http://fangjian0423.github.io/2016/06/04/java-thread-state/
Java线程的生命周期中,存在几种状态。在Thread类里有一个枚举类型State,定义了线程的几种状态,分别有:
- NEW: 线程创建之后,但是还没有启动(not yet started)。这时候它的状态就是NEW
- RUNNABLE: 正在Java虚拟机下跑任务的线程的状态。在RUNNABLE状态下的线程可能会处于等待状态, 因为它正在等待一些系统资源的释放,比如IO
- BLOCKED: 阻塞状态,等待锁的释放,比如线程A进入了一个synchronized方法,线程B也想进入这个方法,但是这个方法的锁已经被线程A获取了,这个时候线程B就处于BLOCKED状态
- WAITING: 等待状态,处于等待状态的线程是由于执行了3个方法中的任意方法。 1. Object的wait方法,并且没有使用timeout参数; 2. Thread的join方法,没有使用timeout参数 3. LockSupport的park方法。 处于waiting状态的线程会等待另外一个线程处理特殊的行为。 再举个例子,如果一个线程调用了一个对象的wait方法,那么这个线程就会处于waiting状态直到另外一个线程调用这个对象的notify或者notifyAll方法后才会解除这个状态
- TIMED_WAITING: 有等待时间的等待状态,比如调用了以下几个方法中的任意方法,并且指定了等待时间,线程就会处于这个状态。 1. Thread.sleep方法 2. Object的wait方法,带有时间 3. Thread.join方法,带有时间 4. LockSupport的parkNanos方法,带有时间 5. LockSupport的parkUntil方法,带有时间
- TERMINATED: 线程中止的状态,这个线程已经完整地执行了它的任务