synchronized隐式锁分析

来源:互联网 发布:非线性最优化 编辑:程序博客网 时间:2024/05/20 20:46
package com.ai.runner.test.lock;import java.sql.Timestamp;/** * synchronized 为隐式锁 * 原理:是通过对象内部的一个叫做监视器锁(monitor)来实现的。 * 但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。 * 而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么Synchronized效率低的原因 *  * ******************************************************** *  *  * 测试类SynchronizedTest加载的时候首先在方法区中保存了就该类的信息,静态变量,常量等。在堆区创建了一个SynchronizedTest.clss class对象 * 随后在生产出SynchronizedTest对象test,test2 *  *  *  * 通过字节码观察可发现:方法加锁,代码块加锁,静态方法加锁,synchronized(SynchronizedTest.class)加锁原理 * (注意类对象和该类创建的对象内部都是存在一个监视器锁(monitor))已下4中情况则是通过去获取对象的监视器锁还是类对象的监视器锁,而实现的线程并发访问 *  * (1)方法加锁 : 方法标志中存在标识ACC_SYNCHRONIZED,该标识表示线程去获取对象监视器monitor锁 * (2)代码块加锁:通过monitorenter,monitorexit 去获取对象监视器monitor锁 * (3)静态方法加锁:方法标志ACC_STATIC,ACC_SYNCHRONIZED 表示线程去获取对象监视器monitor锁 * (4)synchronized(SynchronizedTest.class)加锁:去获取SynchronizedTest class 对象的监视器monitor锁 *  *  * @date 2017年4月18日 * @author zhoushanbin * */public class SynchronizedTest {public static void main(String args[]){final SynchronizedTest test = new SynchronizedTest();final SynchronizedTest test2 = new SynchronizedTest();new Thread(){@Overridepublic void run() {test.testSyn4();}}.start();new Thread(){@Overridepublic void run() {test2.testSyn4();}}.start();}/** * 字节码 * 方法标志中有一个标志ACC_SYNCHRONIZED * JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置, * 如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。 * 在方法执行期间,其他任何线程都无法再获得同一个monitor对象。 * 该monitor属于对象 * @author think * @ApiDocMethod * @ApiCode * @RestRelativeURL */public synchronized void testSyn2(){System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"进入"+"testSyn2()");try {Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}finally{System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"退出"+"testSyn2()");}}/** * 字节码 * 通过monitorenter,monitorexit去持有和释放属于该对象的监视器monitor锁 * 异常时也会释放monitor锁:monitorexit * 该monitor属于对象 * @author think * @ApiDocMethod * @ApiCode * @RestRelativeURL */public  void testSyn3(){synchronized(this){System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"进入"+"testSyn3()");try {Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}finally{System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"退出"+"testSyn3()");}}}/** * 字节码中 * synchronized(SynchronizedTest.class)去申请获取类对象中的监视器monitor锁 * @author think * @ApiDocMethod * @ApiCode * @RestRelativeURL */public  void testSyn4(){synchronized(SynchronizedTest.class){System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"进入"+"testSyn4()");try {Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}finally{System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"退出"+"testSyn4()");}}}/** * 字节码中 * 方法标志中标识:ACC_PUBLIC,ACC_STATIC,ACC_SYNCHRONIZED * ACC_STATIC,ACC_SYNCHRONIZED 这两个标识表示:该方法获取的是类对象的monitor监视器锁  * @author think * @ApiDocMethod * @ApiCode * @RestRelativeURL */public  synchronized static void testSyn5(){System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"进入"+"testSyn5()");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}finally{System.out.println(new Timestamp(System.currentTimeMillis()).toString()+":"+Thread.currentThread().getName()+"退出"+"testSyn5()");}}}


0 0