synchronized是java提供的原子性内置锁,也被称为监视器锁。
synchronized修饰同步代码块,会在编译之后的同步的代码块前后加上monitorenter和monitorexit字节码指令,它依赖操作系统底层互斥锁实现。它的作用主要就是实现原子性操作和解决共享变量的内存可见性问题。
从内存语义来说,加锁的过程会清除工作内存中的共享变量,再从主内存读取,而释放锁的过程则是将工作内存中的共享变量写回主内存。
执行monitorenter指令时会尝试获取对象锁,如果对象没有被锁定或者已经获得了锁,锁的计数器+1。此时其他竞争锁的线程则会进入等待队列中。
执行monitorexit指令时则会把计数器-1,当计数器值为0时,则锁释放,处于等待队列中的线程再继续竞争锁。
synchronized底层有两个队列waitSet和entryList。
1、当多个线程进入同步代码块时,首先进入entryList
2、有一个线程获取到monitor锁后,就赋值给当前线程,并且计数器+1
3、如果线程调用wait方法,将释放锁,当前线程置为null,计数器-1,同时进入waitSet等待被唤醒,调用notify或者notifyAll之后又会进入entryList竞争锁
4、如果线程执行完毕,同样释放锁,计数器-1,当前线程置为null
锁升级的状态从低到高依次为无锁->偏向锁->轻量级锁->重量级锁。
1、进入同步代码块后,Mark Word判断是否是偏向锁;如果是,Mark Word判断是否是当前线程id;如果是,获得偏向锁,执行同步代码块;
2、如果不是偏向锁&#