synchronized
关键字原理简单描述
Java中,最基本的互斥同步手段是 synchronized
关键字。
synchronized
关键字经过编译之后,会在同步块的前后分别形成 monitorenter
和 monitorexit
这两个字节码指令。
这两个字节码都需要一个 reference
类型的参数来指明要锁定和解锁的对象。
如果Java程序中的synchronize明确指定了对象参数,那这个对象就是reference;若没明确指定,则根据synchronize修饰的是实例方法还是类方法,
去取对应的对象实例或Class对象来作为锁对象。
根据虚拟机规范的要求,在执行monitorenter指令时,首先要尝试获取对象的锁。
若未锁定,或当前线程已经拥有了那个对象的锁,把锁的计数器加1;相应的,执行monitorexit指令时将锁的计数器减1,当计数器为0时,锁就被释放。
若获取对象锁失败,那当前线程就要阻塞等待,直到对象锁被另一个线程释放。
在虚拟机规范对 monitorenter
和 monitorexit
的行为描述中,有两点特别需要注意。
Java的线程是映射到操作系统原生线程上的。状态转换需要耗费处理器时间。synchronize是Java中一个重量级操作,慎用。