1 、加锁实现原理
public class SynchronizedTest {
public void get(){
synchronized (this){ // 这个是同步代码块
System.out.println("你好呀");
}
}
public synchronized void f(){ //这个是同步方法
System.out.println("Hello world");
}
public static void main(String[] args) {
}
}
反编译
monitorenter:代表 监视器入口,获取锁;
monitorexit:代表监视器出口,释放锁;
monitorexit:第二次monitorexit,代表 发生异常,释放锁;
2、底层实现ObjectMonitor
2.1 ObjectMonitor属性
sychronized 底层实现是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(锁)[notify/notifyAll/wait等方法存在于顶级对象Object中的原因]
ObjectMonitor() {
_header = NULL;// 存储着MarkWord
_count = 0; // 竞争锁的线程个数
_waiters = 0, // wait的线程个数
_recursions = 0; //标识当前synchronized 锁重入的次数
_object = NULL;
_owner = NULL; //持有锁的线程
_WaitSet = NULL; // 处于wait状态的线程,会被加入到_WaitSet
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ; //获取锁资源失败后,线程要放到当前的单向链表中
FreeNext = NULL ;
_EntryList = NULL ; // _cxq以及被唤醒的WaitSet中的线程,在一定机制下,会放到EntryList
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}