深入理解Java虚拟机(第三版)-14. 线程安全与锁优化
14. 线程安全与锁优化
1. 什么是线程安全?
当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替进行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那就称这个对象是线程安全的
2. java语言中的线程安全
我们将java语言下的线程安全分为以下五类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。
1.不可变:不可变一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要进行任何线程安全保障措施。
例如:final修饰的基本类型变量不可变;类不可变,可以通过将类中的字段全部声明为final,比如integer
实例:string,枚举类型,java.lang.number的部分子类,如long和double等数值包装类、biginteger和bigdecimal等大数据类型。但number下的原子类atomicinteger等是可变的
2.绝对线程安全:需要达到1中的条件,一个类要达到”不管运行时环境如何,调用者都不需要进行额外的同步措施“的条件,需要付出高昂甚至不切实际的代价。
java api中标注线程安全的类,都不是绝对的线程安全。例如vector,如果要做到绝对安全,需要在内部维护一组一致性的快照访问才行,每次针对其中元素进行改动时,都要产生新的快照,这样代价很大。
3.相对线程安全:即通常意义上的线程安全,保证对这个对象的单次操作是安全的,调用时不需要额外的保障措施;但是连续的调用操作,需要调用端使用额外的同步手段。
4.线程兼容:对象本身不安全,但是通过调用端正确使用同步手段来保证对象在并发环境下的安全使用。
java中大多数类是线程兼容的,比如hashmap、arraylist
5.线程对立:不管调用方是否采取了同步措施,都无法在多线程环境下保证线程安全。
thread的suspend()和resume();system.setin()和 setout()
3.线程安全的实现方法(倾向于虚拟机如何实现同步与锁)
1.互斥同步
互斥的实现方式:临界区(critical section)、互斥量(mutex)和信号量(semaphore)。
java中,最基本的互斥手段是synchronized,synchronized关键字在经过javac编译之后,会在同步块前后行程moniterenter和moniterexit两个字节码指令。这两个字节码指令都需要一个reference类型的参数来指明要锁定和解锁的对象。如果没有指定,将根据synchronized修饰的方法类型(如实例方法或类方法)来决定线程持有的锁是代码所在的对象实例还是类型对应的class对象。
java虚拟机规范要求,在执行moniterenter时,首先去获取对象的
上一篇: Python连接MYSQL数据库类
下一篇: blob - 二进制文件流下载