zoukankan      html  css  js  c++  java
  • 第十三章 线程安全与锁优化

    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

      

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    【GIS】Vue、Leaflet、highlightmarker、bouncemarker
    【PHP】xampp配置多个监听端口和不同的网站目录(转)
    【ArcGIS】栅格分析-问题之001(转)
    java登录央行征信网站
    登录中国人民银行征信中心
    爬取百度百科上中国所有城市的信息
    pycharm pro版本激活
    一种爬虫架构分享
    中国联通短信验证码
    中国联通通话记录、身份认证、上网记录等信息
  • 原文地址:https://www.cnblogs.com/walker993/p/14654008.html
Copyright © 2011-2022 走看看