1.synchronized关键字最主要有以下3种应用方式
-
修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁
-
修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁
- 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁
2.为互斥锁,保证了可见性
3.在JVM中,对象在堆内存中的布局分为三块区域:对象头、实例数据和对齐填充.
Java头对象,它是实现synchronized的锁对象的基础.其中头对象包括一个名为Mark Word的头对象结构.Mark Word存储对象的hashCode、锁信息或分代年龄或GC标志等信息.synchronized的对象锁,锁标识位为10,其中指针指向的是monitor对象(监视器锁)的起始地址。每个对象都存在着一个 monitor 与之关联,monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个 monitor 被某个线程持有后,它便处于锁定状态。
在Java虚拟机中,monitor是由ObjectMonitor实现的,ObjectMonitor中有两个队列,_WaitSet 和 _EntryList,用来保存ObjectWaiter对象列表( 每个等待锁的线程都会被封装成ObjectWaiter对象),_owner指向持有ObjectMonitor对象的线程,当多个线程同时访问一段同步代码时,首先会进入 _EntryList 集合,当线程获取到对象的monitor 后进入 _Owner 区域并把monitor中的owner变量设置为当前线程同时monitor中的计数器count加1,若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入 WaitSe t集合中等待被唤醒。若当前线程执行完毕也将释放monitor(锁)并复位变量的值,以便其他线程进入获取monitor(锁)。