Java高并发程序设计3
本文主要是两个线程中淘汰的方法:suspend与resume、wait与notify、join与field、volatile。
join:线程方法
两个线程方法:join()与join(long mile)分别表示无限制的等待目标线程结束后执行,另一个是有时间限制的等待。例如:
join的本质是让调用线程wait()在当前线程对象实例上,核心代码片段为wait(0);
yield:
静态方法,会让线程让出CPU资源,但并不能保证不会继续抢占CPU资源
volatile:
在讲volatile之前,回顾一下先验知识JMM:Java内存模型
并行程序比串行程序复杂的最主要原因是并发程序下数据访问的一致性和安全性将会受到严重挑战。为了保证多个线程间可以有效的正确的合作,JMM出现:仅仅围绕多线程的原子性、可见性、有序性展开。
原子性:
数据的原子性指各线程对数据的操作不受其它线程的干扰。比如,一个静态int,一个线程执行赋值1,一个线程执行赋值-1,则两个线程可能执行的顺序不一样(从0到1再到-1或者从0到-1再到1),但线程对数据的操作是不会变的(注:long类型在32为JDK下没有原子性)。
可见性:
当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。如果两个线程没有可见性(不加volatile)可能会出现可见性问题。包括缓存优化或者硬件优化、同时还有指令重排。指令重排指一个线程中的两个操作可能前后顺序会发生改变,从而导致变量的结果不一。
有序性:
一个线程中看到另一个线程中的指令并非顺序执行(注:一个线程下指令是顺序执行的)
针对多线程下的问题,volatile关键字出现:
当你用volatile去申明一个变量,就告诉虚拟机,这个变量极有可能会被某些程序或者线程修改。为了确保这个变量被修改后,应用程序范围内的所有程序都能够看到,虚拟机就必须采取一些特殊的手段,保证这个变量的原子性、有序性、可见性等特点。即long也可以是原子性的、有序的、可见的。
例如:
定义一个线程1中变量为TRUE时停止循环,同时在主线程中设置此变量为TRUE(注:线程1以内部类的形式给出,可同时访问此变量),如果不加volatile并且虚拟机再Server模式下,两个线程间的可见性无法满足,便不会告知,也不会停止循环。
说明:用volatile可以解决变量的原子性、可见性、有序性问题,但无法保证一些复合操作的原子性,比如i++等。