一、syn锁住的是对象,对象里边的组成如下:
Java的对象布局
必须是要求对象的大小必须是8的整数倍
1.首先是有一个object header
2.填充数据 :当对象大小不足8的倍数的时候,他会把当前对象填充成8的倍数,假如他现在本身就是8的byte的倍数,此时填充数据就不用了
3.成员变量 :就是咱们成员变量
二、锁升级
2.1 偏向锁
线程要尝试去加锁,他会去判断当前这个mark-word里边是否包含线程id,如果没有线程id的话,他会去利用cas把自己的线程id写入到mark-word里边去第二次这个线程再次过来的时候,他会去判断当前这个mark-word里边是否包含线程id,如果有了的话,他就会把他自己的线程id和对象头里边的线程id进行对比,如果发现是一样的此时就标识获得到了锁
如果你在没加锁的情况打印对象头:他默认就是 无锁可偏向,如果你没加锁的情况计算了hashCode码,无锁不可偏向,
如果此时你加锁无法成为偏向锁,直接膨胀成一把轻量级锁
2.2 轻量级锁
1、 升级成轻量级锁三个条件
a、你现在已经是无锁不可偏向,此时加锁那么他就直接是一把轻量级锁
b、没有关闭延迟偏向锁打开,他会自动成为轻量级锁
c、如果程序出现交替执行,他也会成为一把轻量级锁
2、原理
a、首先方法压栈,此时这个方法栈帧就压栈,栈帧种就创建两个和锁有关系的空间 displace hrd ,owner
b、他会将锁里边的mark-word里边信息拷贝到hrd种
c、他会用栈帧owner 指针去指向我们的对象头
d、对象头中轻量级指针会指向当前创建出来的这个栈帧
e、锁会把当前的状态修改成00
f、如果说完成了以上4件事情,那么此时才表示加锁成功,这把锁就是属于当前线程的
2.3 重量级锁
1、原理
a、Java如果发现要创建一把重量级锁,我们Java就会为我们创建一个C++的ObjectMonitor,会让对象头中monitor指向我们这个ObjectMonitor对象如果你进入到锁内部时,这个ObjectMonitor他会 发起汇编指定 monitorenter,当你出syn代码代码块的时候,他会发出monitorexit指令如果你在执行syn过程中出现了异常,其实上他还是会执行monitorexit这样一个指令
b、对象头里边monitor指针会指向 ObjectMonitor 对象,当多个线程来加锁的时候他,他们就会执行monitorenter 指令,进入到 ObjectMonitor进入到entrylist中等待抢锁,他们会利用cas 来进行抢锁,如果抢锁成功,ObjectMonitor,他会把他内部的owner的指针去指向咱们抢锁成功 线程,然后会让计数器+1,如果此时是抢锁的线程是持有锁的线程,那么此时count就会再+1 ,释放锁的时候,把count进行--,直到count== 0的时候就把owner 置为null,如果你对线程调用wait方法,此时这些被wait的线程他就会进入到waitSet中,只有当你去调用notifyall方法的时候他才会从新开始这样一套流程
c、如果是同步方法,那么他执行的 指令 acc_synchronized ,但是这哥们是隐式调用