java锁-synchronized
详细讨论java中synchronized关键字底层加锁原理和应用。
文章目录
前言
对于学习了java的读者而言synchronized关键字肯定不会陌生, 初步学习java时synchronized就是锁的代名词,还有一部分人总是将synchronized当成万能锁来用。本文将详细讨论synchronized在jvm底层是如何加锁?滥用synchronized会面临怎么样的后果?应该如何合理使用?
1. 原理
被synchronized修饰的java代码块或方法通过javac编译为字节码后,会在同步代码的前后生成monitorenter和monitorexit这两个字节码指令,这两个指令都需要一个reference类型的参数来明确锁定和解锁的对象(线程持有锁对象)。如果在java源码中显示的定义了synchronized参数对象则使用该参数的引用作为reference,如果synchronized没有指定参数,会根据synchronized修饰的方法(实例方法或静态方法)来决定是选择对应的实例对象还是Class对象作为reference。
1.1 monitorenter和monitorexit指令
执行monitorenter指令时首先会尝试获取对象锁,如果这个对象没有被锁定或者是当前线程已经持有这个对象锁,则把锁的计数值加一。而执行monitorexit指令时会将锁的计数值减一,一旦锁的计数值为零,当前线程立即释放锁。如果monitorenter指令获取对象锁失败,则会将当前线程阻塞等待。
2. 性能
synchronized在jdk1.5版本之前(包括1.5)采用重量级锁(将线程直接挂起或唤醒)在多线程环境下频繁切换