⑤. monitorexit
①. 能执行monitorexit指令的线程一定是拥有当前对象的monitor的所有权的线程
②. 执行monitorexit时会将monitor的进入数减1。当monitor的进入数减为0时,当前线程退出monitor,不再拥有monitor的所有权,此时其他被这个monitor阻塞的线程可以尝试去获取这个monitor的所有权
③. monitorexit释放锁
(monitorexit,指令出现了两次,第1次为同步正常退出释放锁;第2次为发生异步退出释放锁)
monitorexit插入在方法结束处和异常处,JVM保证每个monitorenter必须有对应的monitorexit
④. 面试题synchroznied出现异常会释放锁吗?
会释放锁
⑥. 再来谈谈同步方法
①. synchronized普通同步方法
(调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程会将先持有monitor然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放minotor)
②. 从编译的结果来看,方法的同步并没有通过指令monitorenter和monitorexit来完成(理论上其实也可以通过这两条指令来实现),不过相对于普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的。当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象
③. 两种同步方式本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。两个指令的执行是JVM通 过调用操作系统的互斥原语mutex来实现,被阻塞的线程会被挂起、等待重新调度,会导致"用户态和内核态"两个态之间来回切换,对性能有较大影响