网站安全专家 2019-05-19
第十三章 线程安全和锁优化
线程安全:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用
方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的
java中的线程安全
各种操作共享的数据分为以下五类
1) 不可变 不可变对象一定是线程安全的,String,常用枚举类,Long和Double等数值的包装类型,BigInteger,Bigdecimal等;AtomicInteger,AtomicLong并非不可变对象
2)绝对线程安全
3)相对线程安全 java.util.Vector,HashTable,Collections的synchronizedCollection()方法包装的集合
4)线程兼容 对象本身并不是线程安全的,但是可以通过调用端正确的使用同步手段来保证对象在并发情况可以安全的使用
5)线程对立 无论调用端采用同步措施,would无法在多线程环境中并发使用的代码,如System.setIn(),System.setOut();
线程安全的实现方法
1)互斥同步(阻塞同步)
临界区,互斥量,信号量是主要的互斥的实现方式
最常用的互斥手段,synchronized
J.U.C下的ReentrantLock
ReentrantLock 比synchronized 多一些功能
1)等待可中断 当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情,可中断特性对处理执行时间非常长的同步快很有帮组
2)可实现公平锁 多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁
3)锁可以绑定多个条件 一个ReentrantLock 绑定多个Conditiion
所以1.6之后提倡使用synchronized,对它进行了优化
2) 非阻塞同步
基于冲突检测的乐观并发策略,就是先进行操作,如果没有其他线程争用共享数据,那操作就成功了;如果共享数据有争用,产生了冲突,那就采取其他措施(不断的尝试,直到成功为止)
CAS compare and Swap 比较并交换
如果在这段期间,它的值曾经被改变成了B,后来又被改回A,那CAS操作就会认为它没有改变 CAS的“ABA”问题
3) 无同步方案
可重入代码
线程本地存储
锁优化
1) 自旋锁和自适应自旋
自旋锁:让线程执行一个忙循环(自旋)
-XX:+UseSpinning 来开启,默认关闭
2)锁消除
虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除
3)锁粗化
就是加的锁太多,将加锁同步的范围扩展到整个操作序列的外部
4)轻量级锁
传统锁时重量级的,轻量级时指在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗
无竞争的情况下使用CAS 去消除同步使用的互斥量
5)偏向锁
无竞争的情况下把整个同步都消除掉,连CAS操作都不用做了