Java 线程安全和锁优化
4.1 概述
线程安全即为多个进程无论如何调用一个代码块,它都是安全的,这样称为线程安全
弱化定义:单次调用对象的行为无需担心多线程,即为线程安全
4.2 Java中的线程安全
1.不可变类型:
Immutable 对象一定是安全的,类似于string类型
2.绝对线程安全
所有代码块和方法全部使用synchronized修饰
3.相对线程安全
一些线程安全类,vector,hashtable等
4.线程兼容
ArrayList 和Hashmap
5.线程对立
4.3 线程安全的实现方法
1.互斥同步(Mutual Exclusion& Synchronization)
多个线程并发访问数据时同一时刻只能被一个线程使用
主要实现手段是synchronized,是一个重量级操作,因为需要经常切入到内核态中。
还可以使用ReentrantLock来实现同步,有等待可中断,可实现公平锁以及锁可以绑定多个条件,这3个特性
2.非阻塞同步
基于冲突检测到乐观并发策略,先进行操作,如果没有其他线程争用那就没问题;如果有其他线程争用,那就再采取其他的补偿措施。
比如CAS指令:比较并交换,但是会有ABA问题
3.无同步方案
1,可重入代码
特点是不依赖堆上的数据和公用系统资源,返回值可以预测
2,线程本地存储
4.4 锁优化
4.4.1 自旋锁与自适应锁
让线程忙循环而并不挂起,这样就不需要切入内核态了
自旋的次数默认是10次,超过10次就挂起
自适应就是根据经验来判断自旋时间和次数
4.4.2 锁消除
去除一些代码上要求同步但是实际上被检测到不可能出现共享数据竞争的锁,将其消除掉的过程。
4.4.3 锁粗化
一个代码块频繁的加锁,虚拟机会对这个代码块直接加锁
4.4.4 轻量级锁
大部分锁在同步过程中都是没有竞争的,使用CAS操作实现
4.4.5 偏向锁
如果没有线程尝试获取锁,则无需加锁;
如果有,则偏向结束。