深入JVM 线程安全分级
线程安全:当多个线程访问一个对象,如果不需要考虑这些线程在运行时环境的调度和执行,也不需要额外的同步,或者调用方进行协调,调用执行的结果总是正确的,那么这个对象是线程安全的
在Java中按照安全等级可以将共享数据划分成5类
——不可变
不可变的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要采用任何线程安全保障,final关键字:只要一个不可变对象被创建出来,那其外部的可见状态永远不会改变,不必考虑在多线程中的不一致性
在语言层面,如果共享数据是一个基本数据类型,那么只要在定义时使用final关键字修饰即可保证它的不可变。如果共享数据是一个对象,那就需要保证对象的行为不会对其状态产生影响,如 java.lang.String对象,它是一个典型的不可变对象,调用substring() replace() concat()方法都不会影响原先的值,只会返回新构建的字符串对象
——绝对线程安全
所谓绝对线程安全即和线程安全定义一致,但是为了达到这个定义要求,需要很大的代价,所以通常Java语言的线程安全离绝对线程安全有一定差距,如java.util.Vector是一个线程安全的容器,因为它的方法add() get() size()都是被synchronized关键字修饰的,尽管效率很低,但确实是安全的,但是即使它的所有方法被修饰成同步,也不意味者不需要同步手段
案例:
[code]public class VectorTest { private static Vector<Integer> vector=new Vector<Integer>(); public static void main(String[] args) { // TODO 自动生成的方法存根 while(true) { for(int i=0;i<10;i++) vector.add(i); Thread removeThread=new Thread( new Runnable() { @Override public void run() { for(int i=0;i<vector.size();i++) vector.remove(i); } } ); Thread printThread=new Thread( new Runnable() { @Override public void run() { for(int i=0;i<vector.size();i++) System.out.println(vector.get(i)); } } ); removeThread.start(); printThread.start(); while(Thread.activeCount()>20); } } }
这段程序实际运行过程中会出现ArrayIndexOutOfBoundsException异常,因为如果一个线程恰好在错误的时间内删除了一个元素,导致序号i不可用,再用i访问数组就会抛出异常,所有仍然需要在读写vector进行必要的同步
——相对线程安全
相对线程安全即通常意义上的线程安全,它需要保证对对象单独的操作是线程安全的,调用的时候不需要额外的保障措施,但是对于一些特定顺序的连续调用,就需要一定的同步手段
大部分线程安全类属于此类型,如Vector HashTable Collections的sychronizedCollecton方法
——线程兼容
线程兼容指对象本身不是线程安全,但可以通过在调用端使用同步手段保证对象在对象环境下的安全,如与Vector HashTable相对的ArrayList HashMap
——线程独立
线程独立是指无论调用端是否采用同步措施,都无法在多线程中并发使用的代码,一个线程对立的例子是Thread类的suspend和resume方法,如果2个线程同时持有一个线程对象,一个试图去中断线程,一个试图去恢复线程,在并发环境下,无论调用是否进行了同步,目标线程都存在死锁的风险,因此高版本的JDK废弃了这些方法
- 【深入理解JVM】第10~13章 编译期优化、线程安全、锁优化 笔记
- JVM虚拟机深入---线程安全
- 【目录索引】深入理解JVM索引
- 深入理解JVM
- 深入理解JVM—JVM内存模型
- 深入理解可重入与线程安全
- [置顶] 深入理解JVM 一GC(下) G1 Garbage Collector
- 【《深入解析Java Web技术内幕》学习思维导图】第7章 JVM体系结构与工作方式
- 深入JVM——OOM异常解析
- 深入理解jvm之java内存管理
- 深入理解jvm之一【内存区域】
- 深入理解jvm—分析
- 深入理解JVM—第一章:走进JAVA
- 深入理解JVM(重要)
- 深入理解JVM
- 深入理解JVM内幕
- 深入理解JVM(三)——JVM之判断对象是否存活(引用计数算法、可达性分析算法,最终判定),Eclipse设置GC日志输出,引用
- 深入理解JVM垃圾回收
- 深入理解JVM(八)——类加载的时机
- JVM内存管理:深入Java内存区域与OOM、深入垃圾收集器与内存分配策略