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 ;}