• 第十三章 线程安全与锁优化


    13.2.2 线程安全的实现方法

      同步:保障线程安全的一种手段,多线程并发访问共享数据时,保证共享数据在同一时刻只被一条(或一些)线程使用。

      1. 互斥同步:互斥是实现同步的一种手段。比如synchronized关键字,Lock接口的实现。synchronized是一个重量级锁,阻塞和唤醒线程涉及到用户态和内核态的切换

      2. 非阻塞同步:互斥同步面临的问题是阻塞和唤醒带来的性能的开销。非阻塞采用乐观同步思路,先进行操作,如果操作完毕准备替换时发现此过程中产生竞争,则采用补偿措施例如重试,直到没有竞争为止。这种同步方式不会阻塞线程。

      3. 无同步方案:从设计上消除竞争,比如可重入代码,变量线程本地存储。

    13.3 锁优化

      优化synchronized的加锁策略,减少加锁性能消耗

      13.3.1 自旋锁和自适应自旋

      在线程获取锁失败时,不是立马进入阻塞,基于锁很快释放的假设,进入一个空转,在这个期间如果获得锁,则省去了阻塞和唤醒的开销,适用锁占用时间很短的情况。缺点是此时会一直占用CPU资源,可以通过配置设置自旋次数,当自旋开启后,默认自旋10次。

      自适应自旋,让自旋次数变得智能,如果在一个锁上,经常等待超时,那么会缩短等待次数,相反如果经常很快就能获得锁,那么自动会延长等待次数。

      13.3.2 锁消除

      虚拟机会对不可能存在共享数据竞争的锁进行消除,判定的依据是逃逸分析技术。

      13.3.3 锁粗化

      虚拟机检查到一连串零碎的操作都是对同一个对象加锁,会将加锁同步的范围扩大。

      13.3.4 轻量级锁

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

      实现轻量级锁需要了解对象头的内存结构。对象头分为Mark Word,引用类型指针和数组大小三个部分,Mark Word的结构分为:25bit的哈希码,4bit的分代年龄,1bit的偏向模式,2bit的标志位。其中标志位01-未锁定,00-轻量级锁定,10-重量级锁定,11-GC标记。

      13.3.5 偏向锁

      旨在无竞争的情况下,一个线程占有锁期间内,再次请求锁直接重入而不需要CAS操作。

      具体操作是,当对象第一次加锁时,线程将对象的标志位设置为01,将偏向标志设置为1,进入偏向模式。同时使用CAS将本线程的ID记录到对象的Mark Word上的哈希码部分(用了23bit),如果成功,下次同一线程再次进入时,将不需要其他操作。一旦有其他线程尝试加锁,会取消偏向模式。

      上面说到占用的内存是对象头的哈希码部分,哈希码一旦生成无法更改,所以一旦有了哈希码之后,将无法在进入偏向模式。并且在偏向模式的状态下,如果有计算哈希码的请求,也将退出偏向模式,进入重量级锁状态,这个时候Mark Word指向ObjectMonitor对象,这其中有字段记录Mark Word,可以将哈希码写入到进入。

    13.4 synchronized底层实现

       参考:https://www.cnblogs.com/walker993/p/14664599.html

      

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    7月15日考试 题解(链表+状压DP+思维题)
    暑假集训日记
    C# .NET 使用 NPOI 生成 .xlsx 格式 Excel
    JavaSE 基础 第42节 局部内部类
    JavaSE 基础 第41节 匿名内部类
    JavaSE 基础 第40节 内部类概述
    JavaSE 基础 第39节 接口的应用
    JavaSE 基础 第38节 接口的实现
    JavaSE 基础 第37节 接口概述
    JavaSE 基础 第36节 抽象类概述与使用
  • 原文地址:https://www.cnblogs.com/walker993/p/14654008.html
Copyright © 2020-2023  润新知