Java并发编程专题


两个关键词 volatile synchronized

  • volatile:保证在多核处理器下,所有线程看到的变量的值是一致的。(volatile还有一个语义为禁止指令重排序,此处暂且不表)

    • 要解释volatile,就不得不提CPU的三层缓存结构:
      ​​​​​​​​​​​​在这里插入图片描述
      cache line:现代操作系统,核心在计算时,一般是按照缓存行(cache line)来进行处理的。每次从内存加载数据时,为了访问的速度,会将目标数据及其相邻的数据,一起载入缓存,这部分就叫做缓存行,有个大小限制,一般为64bit。缓存与内存的交互都是以缓存行为单位进行的。
      volatile提出背景:作为Java中的普通对象,当Thread1跑在Core1,对独享变量进行了变更时,Core2上的Thread2是不会立刻感知到的。(等到Thread1将更新写回内存,Thread2再从内存中重载这块内存时才能刷新,在此之前,Thread2拿到的都是旧数据)。 所以提出了volatile,当变量需要在线程间共享时,需要在变量前加上volatile关键字。
      原理:volatile变量经过汇编后,会在基础的指令上,增加一个Lock前缀指令。
      • Lock有什么用:
      1. 将当前缓存行的数据刷回内存
      2. 其他Core会监听总线上Lock的动作(MESI)
      • 具体流程:JMM的8中原子操作(read load use assign write store lock unlock)
        1. T1: read-load-use
        2. T2: read-load-use
        3. T1: (lock)assign-store-wrtie (unlock)T2监听到,将cacheline失效
        4. T2有读请求时:read-load-use
      • 支线:MESI:缓存一致性协议,为CPU层面,对缓存行进行的四中标记,以确保各个Core上缓存的一致性:
        • modifide
        • exclusive
        • shared
        • invalid
          各状态间的流转见下图:
          在这里插入图片描述
  • synchronized:对线程对临界区代码的访问进行加锁控制

    • 锁的什么东西:
      • 普通同步方法:锁定实例对象
      • 静态同步方法:锁定当前类对象
      • 同步方法块:锁定括号中配置的对象。
    • 实现:通过在临界区代码块的前后插入指令实现。
    • 先来谈谈Java对象头(以64bit为例)
      • Mark word(64bit) 锁信息或hashCode
        无锁情况下的对象头:
        在这里插入图片描述
        施加偏向锁时的对象头:
        在这里插入图片描述

      • Class MetaData(64bit) 类指针

      • array length(32bit):数组大小(也说明数组最长只能到 2^31-1,这也是通过构造函数能创建的,最长的字符串长度了)。

    • 在Java 1.6之前,所有的锁都是重量级的,但是经过数据分析后发现,并发场景下的大部分锁往往只由一个线程进行了访问,也以此做出假设,在Java1.6中引入了锁升级机制。
      • 锁状态:无锁、偏向锁、轻量级锁、重量级锁
      • 相关前情提要:
        • CAS: compare and swap 原子操作
      • 锁升级流程:(私信获取原图)
        在这里插入图片描述
        偏向锁:同时只有一个线程时,用户态
        轻量级锁:2个线程产生竞争时,用户态
        重量级锁:当第二个线程在CAS自旋等待时。为了避免多数的线程CAS自旋造成的CPU浪费,在内核态,通过重量级锁,将CAS自旋的线程进行挂起。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值