《Java并发编程的艺术》读书笔记(一)

并发机制底层实现原理

  • volatile
    使用volatile修饰的变量,在编译的时候会加上LOCK前缀加锁指令,LOCK前缀会使处理器执行当前指令时产生一个LOCK#信号,这个总是会引起显式总线的锁定。
    1)LOCK前缀指令会引起处理器缓存回写到内存
    2)一个处理器的缓存回写到内存会导致其他处理器的缓存无效

    volatile使用优化:缓存行填充。缓存行不支持部分填充并且也不能部分提取,如果不同的数据读取到同一个缓存行,则会增加缓存行被锁定的概率。比如Disruptor框架中SingleProducerSequencer.Padding,其源码如下:

    public long nextValue;
    public long cachedValue;
    public long p2;
    public long p3;
    public long p4;
    public long p5;
    public long p6;
    public long p7;
    
    private Padding() {
        this.nextValue = -1L;
        this.cachedValue = -1L;
    }

    SingleProducerSequencer.Padding使用了额外的6个long型变量,SingleProducerSequencer.Padding共占64个字节,对于64字节的缓存行就刚好铺满一个缓存行。对于其他不是64字节的缓存行,SingleProducerSequencer.Padding也不能处理伪共享的问题。

  • synchronized
    synchronized通过加锁方式来实现同步,有三种形式:

    • 普通的同步方法,锁是当前对象
    • 静态同步方法,锁是当前类的Class的对象
    • 同步方法块,锁是synchronized括号里的对象

synchronized用的锁在java对象的头里。有两种情况:数组对象,虚拟机使用3个字宽存储对象头。非数组对象,则使用2个字宽来存储对象头。32位虚拟机中,1个字宽等于4字节,即32字节。

长度内容说明
32/64bitmark word存储对象的hashCode或者锁信息
32/64bitClass metadata address存储对象描述数据的指针
32/64bitmark word存储对象的hashCode或者锁信息

其中mark word具体存储格式如下:

mark word状态
对象的hashCode:25bit | 对象分代年龄:4bit | 偏向锁标识:1bit | 锁标志位:2bit(01)无锁状态
线程ID:23bit | 标识偏向锁是否有效:2bit | 对象分代年龄:4bit | 偏向锁标识:1bit | 锁标志位:2bit(01)偏向锁
指向栈中锁记录的指针:30bit | 锁标志位:2bit(00)轻量级锁
指向互斥量的指针:30 | 锁标志位:2bit(10)重量级锁
空 | 锁标志位:2bit(11)GC标记

锁的级别从低到高依次为:无锁状态–>偏向锁–>轻量级锁–>重量级锁。锁可以随着竞争情况进行升级,但不能降级。
64位的对象头如下:

mark word状态
空:25 | 对象的hashCode:31bit | 空:1 | 对象分代年龄:4bit | 偏向锁标识:1bit | 锁标志位:2bit(01)无锁状态
线程ID:54bit | 标识偏向锁是否有效:2bit | 对象分代年龄:4bit | 偏向锁标识:1bit | 锁标志位:2bit(01)偏向锁
指向栈中锁记录的指针:62bit | 锁标志位:2bit(00)轻量级锁
指向互斥量的指针:62 | 锁标志位:2bit(10)重量级锁
空 | 锁标志位:2bit(11)GC标记

在64位中,OOP(Ordinary Object Pointers)为64位,在最大堆大小在4G到32G之间,可以采用指针压缩技术来提高性能。从JDK 1.6 update14开始,可以使用:-XX:+UseCompressedOops开启指针压缩,java7 之后默认开启,如果最大堆大小符合条件。指针压缩会将OOP压缩为32位,32位的指针怎么映射到大于4G内存上呢?压缩指针会在右侧补上3位0,也即会乘以8,然后得到操作系统的指针地址.

那么只有4G的地址怎么使用到32G的堆内存呢?在JVM中,32位寻址地址代表的是4G个对象的指针,不是4G字节。而在32位JVM中,一个对象的对象头至少有8字节,在64位JVM中至少有16+8(压缩指针)=24字节。所以不论怎样,4G个指针所指向的对象都能达到4G*8=32G字节。

参考资料:
1、java object header
2、compressed oop

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值