synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。synchronized的作用主要有三个:
synchronized从语法上讲有3种使用方式
先通过javap反编译一段的代码来看看synchronized是如何实现对代码块进行同步的:
public class TestTest {
public void test(){
synchronized (this){
Object o= new Object();
}
}
}
反编译结果:
和不加synchronized关键字对比,编译结果主要多出了monitorenter和monitorexit指令,通过jvm规范手册找到说明
monitorenter指令:https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-6.html#jvms-6.5.monitorenter
Description
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
简单翻译下
每个对象都有一个关联的监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
monitorexit指令:https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-6.html#jvms-6.5.monitorexit
Description
简单翻译下
当synchronized关键字修饰到方法上时
public class TestTest {
public synchronized void test(){
Object o= new Object();
}
}
反编译结果
同步方法上并没有和同步块一样的使用monitorenter和monitorexit指令(理论上其实也可以通过这两条指令来实现),不过在方法访问标识符(flags)中加入ACC_SYNCHRONIZED 标志
jvm规范手册的说明:https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-2.html#jvms-2.11.10
Method-level synchronization is performed implicitly, as part of method invocation and return (§2.11.8). A synchronized method is distinguished in the run-time constant pool's method_info structure (§4.6) by the ACC_SYNCHRONIZED flag, which is checked by the method invocation instructions. When invoking a method for which ACC_SYNCHRONIZED is set, the executing thread enters a monitor, invokes the method itself, and exits the monitor whether the method invocation completes normally or abruptly. During the time the executing thread owns the monitor, no other thread may enter it. If an exception is thrown during invocation of the synchronized method and the synchronized method does not handle the exception, the monitor for the method is automatically exited before the exception is rethrown out of the synchronized method.
简单说明
同步方法时隐式执行的,同步方法在运行时会在常量池的method_info结构中放入ACC_SYNCHRONIZED标志,当线程访问方法时,会去检查是否存在ACC_SYNCHRONIZED标志,若存在,则需要获取关联的监视器monitor锁(和monitorenter指令一样),然后执行方法。无论方法调用是正常完成还是发生异常都会释放关联的监视器monitor锁。
通过这里可以知道synchronized关键字实际底层是通过一个叫监视器monitor锁的来实现的。每一个对象都有一个相关联的monitor,线程通过修改monitor的进入数从而实现拥有和释放。
记录一个常刷到的面试题:为什么wait()和notify()属于Object类
一般会有两种问法趋向,为什么是在Object类中而不是其他的类,第二个wait()和notify()是和线程相关为什么没有在线程类里面