深入理解java虚拟机 第十三章 线程安全与锁优化
面向过程的编程思想:
程序员会把数据和过程分别作为独立的部分来考虑,数据代表问题空间中的客体,程序代码用于处理这些数据,
这种思维方式站在计算机的角度去抽象问题和解决问题
面向对象的编程思想:
把数据和行为都看做是对象的一部分,程序员能以符合现实世界的思维方式来编写和组织程序,
这种思维方式是站在现实世界的角度去抽象和解决问题
线程安全
当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步
或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的
java语言中的线程安全
java语言中各种操作共享的数据分为以下5类:
1 不可变
一定是线程安全的,如果共享数据是一个基本数据类型,只要在定义时使用final关键字就可以
2 绝对线程安全
一个类要达到不管运行时环境如何,调用者都不需要任何额外的同步措施,通常需要付出很大的,
甚至是不切实际的代价,在java API中标注自己是线程安全的类,大多数都不是绝对的线程安全
3 相对线程安全
相对的线程安全就是我们通常意义上的线程安全,
4 线程兼容
对象本身不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全使用
5 线程对立
无论如何,都无法在多线程环境中并发使用的代码
线程安全的实现方法
1 互斥同步
常见的并发正确性保障手段,同步是指多个线程并发访问共享数据时,保证共享数据在同一时刻只被一个线程使用
互斥是实现同步的手段,临界区、互斥量、信号量都是主要的互斥实现方式
最基本的互斥手段是synchronized关键字,在经过编译后,会在同步块的前后分别形成monitorenter和monitorexit
这两个字节码指令
还可以使用java.utile.concurrent包中的重入锁(ReentrantLock)来实现同步
提倡在synchronized实现需求的情况下,优先使用
2 非阻塞同步
基于冲突检测的乐观并发策略
3 无同步方案
要保证线程安全,不一定就要进行同步,两者没有因果关系,
1 可重入代码:纯代码
2 线程本地存储
锁优化
1 自旋锁与自适应自旋
让后面请求锁的那个线程"稍等一下",但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁
JDK1.6引入自适应的自旋锁,意味着自旋的时间不再固定了,由前一次在同一个锁上的自旋时间及锁的拥有者的状态决定
2 锁消除
指虚拟机即时编译器在运行时,对一些代码上要求同步,但被检测到不可能存在共享数据竞争的锁进行消除
3 锁粗化
如果一系列的操作都对一个对象反复加锁和解锁,甚至加锁操作出现在循环体中,那即使没有线程竞争
频繁的互斥同步操作也会导致不必要的性能损耗
4 轻量级锁
5 偏向锁

浙公网安备 33010602011771号