简述JVM基础(八):线程安全和锁优化

作者 | 井方哥

地址 | https://zhuanlan.zhihu.com/p/31612647

声明 | 本文是 井方哥 原创,已获授权发布,未经原作者允许请勿转载



前言

我们通过前面的学习,已经知道了工作内存和主内存的8大原子操作,以及Java线程的实现方式,和状态关系。我们清楚:

  • 高效并发首先要保证并发的准备性,而后才是高效。

本篇还解答了如下问题:

  • 什么是线程安全?

  • 实现线程安全有哪些方法?

  • 锁优化有哪些方案?


线程安全

1、定义

多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替,也不需要额外的同步,或者调用方进行其他的协同操作,调用这个方法的行为最终都能够获得正确的结果,那这个对象是线程安全的。

2、Java中线程安全分类

  • 不可变:

    • final(未发生this逃逸)

    • java.lang.String:进行subString()、replace()、concat()不会影响原来的值,而是构建出新的一个不可变的值并返回;

  • 绝对线程安全:不管运行环境如何,调用者都不需要进行额外的同步措施,线程安全不一定就是真的安全

  • 相对线程安全:不需要做额外的同步,但是特定的连续调用顺序的情况下需要同步处理,才能保证调用的结果准确,如Vector\HashTable\Collections的synchronizedCollection()方法包装的集合等;

  • 线程兼容:本身不安全,通过同步处理能够达到安全的效果;Arraylist和HashMap等;

  • 线程对立:无论采取什么同步措施,都不能达到安全效果。如Theard类的supspend()和resume()这两个已被放弃的方法;


线程安全实现方法

1、互斥同步

  • 原则:保证共享数据在同一时刻只能被一个线程访问

  • 互斥是方法,同步时目的

  • synchronized:对于同一条线程来说是可重入的,不会出现把自己锁死的情况

  • java.util.concurrent:重入锁ReentrantLock

    • 等待可中断:持锁线程一直没有释放,等待的线程可以放弃等待

    • 公平锁:多个线程等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁

    • 绑定多个条件:ReentrantLock 调用多次newCondition,绑定多个Condition对象可以实现

  • 优先考虑synchronized,性能差不多。

2、非阻塞同步

  • 原则:不把线程挂起,有错误采取补偿措施;

3、无同步

  • 保证线程安全,不一定要同步;

  • 天生线程安全的代码:

    • 可重入代码:如果一个方法,他的计算结果是可以预测的

    • 线程本地存储:java.lang.ThreadLocal


锁优化

1、自旋锁和自适应自旋

  • 自旋锁:让线程执行一个忙循环(实际让他瞎忙活一会)

  • 自适应自旋:自旋时间有上一次同一个锁自旋时间和锁的拥有者状态来决定

2、锁消除

虚拟机即时编译时发现有些声明了锁,但是实际上没有用的锁(不存在共享数据竞争),直接进行消除

3、锁粗化

本来是锁的范围越小越好,但是对于里面有反复加锁解锁的情况,那就把范围扩大。

4、轻量级锁

  • 目的:没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗

5、偏向锁

  • 锁会偏向于第一个获得它的线程

  • 当有另外的线程尝试获取时,偏向模式宣告结束


小结

线程安全是说在没有额外或者协同的同步处理的情况下,多线程操作共享数据,依然可以得到准备的结果。Java开发中主要通过互斥同步的方案来达到线程安全的目的,其中用到的Synchronized和ReentrantLock。还有记住ThreadLocal可以给线程存储私有的信息。我们在进行同步的时候是通过 来保证的,对于有些没有必要的锁,我们通过一些手段进行优化,进来减少带来的性能开销。

说明: 本系列多处摘抄《深入理解Java虚拟机》中内容,主要精简了本书的要点,并叙述自己对本书的理解。本人才疏学浅,文章中有不对的地方,还望批评指教。


本系列

简述JVM基础(七): Java 内存模型与线程

简述JVM基础(六):虚拟机字节码执行引擎

简述JVM基础(五):虚拟机类加载机制

简述 JVM 基础(四):类结构文件

Android 精进:简述 JVM 基础(三):垃圾收集器与内存分配策略

Android 精进之简述 JVM 基础(二):Java内存区域与内存溢出异常

Android 进阶之简述 JVM 基础(一):走进Java



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值