synchronized关键字
synchronized(同步),也就是用于进行线程同步的关键字,共三种使用情况。
一、用于修饰static方法时
- 此时同步使用的是:class lock : 类锁
- 同步的范围包括,
该类的所有的静态方法
和其实例对象的所有实例对象方法
。
public static synchronized void synMethod() {}
二、用于修饰对象方法时
- 此时同步使用的是:object lock:实例对象锁
- 同步的范围包括,属于
当前实例对象
的所有非static方法
(对象方法)。
public synchronized void synMethod() {}
三、用于修饰方法块时
synchronized(对象/类) {
// ...
}
- 此时同步使用的锁根据参数不同而不同。对象就是对象锁,类就是类锁。
补充理解:
-
锁的范围如何理解?
答:同步其实考虑的是对资源操作的同步, 例如。如果是类锁,首先看,类有哪些资源
--> 类有static成员变量。然后,哪些方法能操作其拥有的资源
--> 类方法和该类的所有实例的对象方法。所以锁的范围就包括这些方法。 -
synchronized的底层实现原理是什么?
答:简单的来说,通过使用jvm所实现的monitorenter指令
和monitorexit指令
。来操作monitor(也就是一把锁)
对象的获取和释放来实现。(每个实例对象都有一把锁(monitor)与之对应)。- 同步代码块:直接的通过
monitorenter指令
和monitorexit指令
实现。[在同步代码块处编译成字节码后,该部分会自动加上异常处理,也就是加了个finally,finnlly里面执行monitorexit指令
,出现异常时也能成功的释放锁,否则可能会死锁] - static和非static同步方法通过:
ACC_SYNCHRONIZED标志
实现(该标志最终也是和同步代码块的实现方式一样)。
- 同步代码块:直接的通过
-
monitor对象,在哪?
每个对象在堆中存储着,实例对象由三部分组成:对象头
、实例变量
和填充数据
。其中对象头
结构中,有一部分就存储着其,monitor对象在栈中的地址。
参考资料:Java synchronized 详解 : http://www.sohu.com/a/273749069_505779