线程安全
是什么
多线程多次执行的情况下,程序不会出现问题
安全方案
线程封闭
- 栈封闭
- 线程本地变量
无状态的类
没有成员变量
不可变类
所有成员变量都有final关键字修饰
如果修饰对象 必须保证对象本身线程安全
加锁或者CAS
使用锁工具
使用synchronized
修改数据使用CAS机制
案例
java中的Date 就是线程不安全的
而1.8 新出的 LocalDate 就是线程安全的
如果方法中传入了Date类型的对象
那么如果被修改了Time 那么其他线程就会看到这个改变
这种改变也许是无意的、不是期望的
两次打印的结果是不一样的
而localDate没有提供任何修改成员变量的方法
因为所有成员变量都是final修饰的
就算有修改需求也是返回对象的拷贝
所以我们认为 LocalDateTime是线程安全的
当然再实际操作Date对象的时候推荐使用lang3包里的DateUtils
常见问题
死锁
条件同时满足才会出现死锁:
- 多个操作者 n1
- 多个资源 n2
- n1 >= n2
- 资源争抢无序
- 抢到后不释放资源
解决
破坏其中一个条件:
- 资源争抢无序
1.1 代码调整
1.2 锁资源排序 - 抢到后不释放资源
2.1 持有资源有限时间
2.1 判断是否持有资源成功 如果不成功则释放所有资源 后重试
活锁
在上边例子2.1中
如果两个线程2把锁 顺序不一致
虽然会释放锁 但是2个线程同时执行到拿第二个资源的时候还是无法拿到
会进入重试
总体会造成CPU 一直在运行 但是卡在获取锁的过程中
解决
拿锁时间错开随机时间
线程饥饿
线程一直拿不到锁