20200426 synchronized底层原理

多线程之间如何通讯(什么是多线程之间通讯)?

多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。

解决线程安全问题:在出现线程安全的代码块上加synchronized关键字.

 

对象锁和类锁

1. 对象锁

在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java 对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。

2. 类锁

在 Java 中,针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。

 

synchronized锁定的是调用这个同步方法的对象(this) 互斥锁,排它锁。

对于静态方法,由于此时对象还未生成,所以只能采用类锁;只要采用类锁,就会拦截所有线程,只能让一个线程访问。

 

同步方法与同步代码块

多线程中考虑,线程获取对象的锁。

1、当同一个对象P1在不同的线程中执行这个同步方法时,他们之间会形成互斥,达到同步的效果。

2、同时如果该对象中有多个同步方法,则当一个线程获执行对象中的一个synchronized方法,则该对象中其它同步方法也不允许别的线程执行;

 

那个拿到了P1对象锁的线程,才能够调用P1的同步方法;而对P2而言,P1这个锁和他毫不相干,程式也可能在这种情形下摆脱同步机制的控制,造成数据混乱。

每个对象对应一个唯一的锁,所以哪个线程拿到这个对象锁谁就能够运行他所控制的那段代码。

monitorEnter;monitorExit.

 

每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitor Enter指令时尝试获取monitor的所有权,过程如下:

1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。

2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.

3、如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。

 

Java对象头与Monitor

在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。

实例变量:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。

填充数据:由于虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐.

 

监视器锁对象:

monitor对象存在于每个Java对象的对象头中(存储的指针的指向),synchronized锁便是通过这种方式获取锁的,也是为什么Java中任意对象可以作为锁的原因,同时也是notify/notifyAll/wait等方法存在于顶级对象Object中的原因。

Java对象头,它实现synchronized的锁对象的基础。

一般而言,synchronized使用的锁对象是存储在Java对象头里的,jvm中采用2个字来存储对象头(如果对象是数组则会分配3个字,多出来的1个字记录的是数组长度),其主要结构是由Mark Word 和 Class Metadata Address 组成。

 

Mark Word 存储对象的hashCode、锁信息或分代年龄或GC标志等信息;

Class Metadata Address 类型指针指向对象的类元数据,JVM通过这个指针确定该对象是哪个类的实例。其中Mark Word在默认情况下存储着对象的HashCode、分代年龄、锁标记位等以下是32位JVM的Mark Word默认存储结构。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值