Synchronized使用、 java对象在JVM内存模型中的构成、 synchronized同步代码块的底层原理、 synchronized同步方法的底层原理
文章目录
参考
https://blog.csdn.net/qq_35190492/article/details/106180781
https://www.cnblogs.com/lukelook/p/9946065.html
https://baijiahao.baidu.com/s?id=1612142459503895416
Synchronized 使用
- 修饰方法
public synchronized void method(){ }
synchronized 关键字不能继承。
- 修饰代码块
synchronized(this){ } synchronized(obj){ }
当一个线程访问一个对象中的 synchronized(this) 同步代码块时,其他试图访问该对象的线程将被阻塞(多个线程可以访问同一个对象,this 指当前对象)
用 synchronized 给 obj 对象加锁,当一个线程访问 obj 对象时,其他试图访问 obj 对象的线程将会阻塞
- 修饰类
synchronized(MyClass.class)
该类的所有对象公用一把锁
java对象在 JVM内存模型 中的构成
-
对象头
Mark Word(标记字段)
默认存储对象的 HashCode,分代年龄 和 锁标志位信息。它会根据对象的状态复用自己的存储空间,也就是说在运行期间Mark Word里存储的数据会随着锁标志位的变化而变化。 -
Klass Point(类型指针)
对象指向它的 类 元数据的指针,虚拟机通过这个指针来确定这个对象是 哪个类的实例。
实例数据
这部分主要是存放类的数据信息,父类的信息。
对齐填充
由于虚拟机要求对象起始地址必须是8字节的整数倍,填充数据不是必须存在的,仅仅是为了字节对齐。
一个空对象占多少个字节?就是8个字节,是因为对齐填充的关系,不到8个字节对其填充会帮我们自动补齐。
synchronized 同步代码块 的底层原理
synchronized 锁住对象,其指针指向该对象的 monitor。
每个对象实例都会有一个 monitor。其中 monitor 可以与对象一起创建、销毁;或者当线程试图获取对象锁时自动生成。
monitor是由 ObjectMonitor 实现(ObjectMonitor.hpp文件)(.hpp 是 C++ 的头文件后缀)
_WaitSet 用来保存每个等待锁的线程对象。
_owner,它指向持有ObjectMonitor对象的线程。
当多个线程同时访问一段同步代码时,会先存放到 _EntryList 集合中,接下来当线程获取到对象的 monitor 时,就会把 _owner 变量设置为当前线程。同时 count变量+1。
如果线程调用wait() 方法,就会释放当前持有的monitor,那么 _owner 变量就会被置为null,同时 _count减1,并且该线程进入 WaitSet集合中,等待下一次被唤醒。
因为这个锁对象存放在对象本身,也就是为什么Java中任意对象可以作为锁的原因。
字节码中在执行 monitorenter 指令时,首先要尝试获取对象锁,也就是上文提到的 monitor 对象。如果这个对象没有被锁定,或者当前线程已经拥有了这个对象的锁,那么就把锁的计数器(_count)加1。当然与之对应执行 monitorexit 指令时,锁的计数器(_count)也会减1。
如果当前线程获取锁失败,那么就会被阻塞住,进入 _WaitSet 中,等待锁被释放为止。
字节码中,有俩个 monitorexit 指令的原因是:编译器需要确保方法中调用过的每条 monitorenter 指令都要执行对应的monitorexit 指令。为了保证在方法异常时,monitorenter和monitorexit指令也能正常配对执行,编译器会多写一个 monitorexit 指令
synchronized 同步方法 的底层原理
字节码中并没有 monitorenter指令和 monitorexit指令,取得代之的是 ACC_SYNCHRONIZED 标识
JVM通过 ACC_SYNCHRONIZED 标识,就可以知道这是一个需要同步的方法,进而执行上述同步的过程,也就是 _count加1 的这些过程。
- java synchronized对象锁与类锁的区别、同步代码块与同步方法的区别
- Java synchronized 对象锁与类锁的区别、同步代码块与同步方法的区别 详解
- Java synchronized 对象锁与类锁的区别、同步代码块与同步方法的区别 详解
- java 对象占用内存查看 以及JVM级别 方法修改等
- 【java回调】同步/异步回调机制的原理和使用方法
- Java练习>卖票案例>>解决线性安全问题的方法(使用同步代码块、同步方法、Lock锁)
- Java使用synchronized修饰方法来同步线程的实例演示
- Java中的synchronized同步代码块和同步方法的区别
- java同步静态方法与非静态方法(使用synchronized关键字)
- java中的synchronized(同步代码块和同步方法的区别)
- Java中的synchronized(同步代码块与同步方法)
- java中的synchronized(同步代码块和同步方法的区别)
- 初学Java多线程:使用Synchronized关键字同步类方法
- 传智黑马Java → 06使用对象类型作为方法返回值的内存图
- Java使用字节码和汇编语言同步分析volatile,synchronized的底层实现
- 九、初学Java多线程:使用Synchronized关键字同步类方法
- java 对象占用内存查看 以及JVM级别 方法修改等
- 【Java面试题】26 多线程有几种实现方法?同步有几种实现方法? 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
- (转)初学Java多线程:使用Synchronized关键字同步类方法
- java中的synchronized同步代码块和同步方法的区别