从Java的对象头到Java内建锁synchronized的底层实现(一)

        就如标题,今天我们的话题会从对象说起。我们知道对象在JVM的内存结构中,是存放在堆内存中的(new  一个类之后JVM会在堆上为new出的对象申请一块空间)。在内存中,一个Java对象包含三部分:对象头、实例数据和对齐填充。而对象头内存有的信息就有mark work,这是实现synchronized锁机制的核心。对象头到底是什么呢?是怎样通过对象头来实现synchronized锁机制呢?这就是这篇博客所要描述的事了。

        首先我看看如下代码,(以下代码就是对象头的描述)

class oopDesc {
  friend class VMStructs;
 private:
  volatile markOop  _mark;
  union _metadata {
    wideKlassOop    _klass;
    narrowOop       _compressed_klass;
  } _metadata;
}

我们可以看到对象头的描述中

(1)有一个友元类

(2)synchronized(内建锁)反复被提到的东西 _mark(也就是常说的mark  word)。其中mark work用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,占用内存大小与虚拟机位长一致。

(3)类型指针(Klass)类型指针指向对象的类元数据,虚拟机通过这个指针确定该对象是哪个类的实例。

        在mark work中就有好多字段是关于synchronized(内建锁)的实现。     我们可以深入的看一看mark  word的类型markOop是怎么描述的。下面是mark word 存有的信息。

(网上查询)

        我们知道Java是一个优化做的很好的语言,我们可以看到mark work中存储信息是分情况,相对不同的锁是保存不同的信息的。所以Java利用这一点先确定是那种锁再动态的分配比特位去存储信息,已达到节省空间的效果。也就是说这时一个非固定的数据结构,利用对象的锁状态来赋予比特位不同的含义。因为一个对象在一个时刻只会有一种锁状态,所以在这个时刻时在32位机上就只用32位,也就是四个字节就可以储存完信息。(64位机上就用64位)

        以上就是我对markwork的初步了解。下面是关于synchronized锁机制的实现。

       对象的锁到底是什么呢?应该怎样理解?系统又是怎样实现的呢?我的理解是对对象的一个标志,也就是对象的对象头中markword所储存的信息。这也就可以理解为什么synchronized锁是加在对象上的,而不是加在代码上了,原因是它本身就是对象头里markword中记录的一个标志,反映给用户就是所说的对象锁。

       我们从上表看到锁状态的表示

 无锁                         (001)     

 偏向锁                     (101)

 轻量级锁                 (00)

 重量级锁                 (10)(阻塞式实现,会把没有竞争到锁的线程挂起,在合适的时候恢复,而这些操作是要经过内核态处理的,会给系统的并发性造成很大的压力)

这个从上到下的排列也就是锁从轻量到重量的一个过程。偏向锁在JDK6后默认启动,有需要的条件下重量级会逐渐升高(这是一种优化)。

重量级升高的过程这涉及到synchronized锁的优化,后面我会用一整篇来描述我的理解。

         

猜你喜欢

转载自blog.csdn.net/a15929748502/article/details/84351074