本章概述
上一篇已经分析过Java中的各种类型的锁,用心的小伙伴会发现上篇文章中已经引出了一些锁的转换过程,多各种锁的性能肯定是存在差异的,本章我们就主要对锁的性能做一些测试,并介绍一些需要注意的细节。
性能对比偏向锁和轻量级锁:
package org.xinhua.cbcloud.jol;public class Test { //boolean flag = false; //占一个字节 int i=0; public synchronized void parse(){ i++; }}
package org.xinhua.cbcloud.jol;public class JOLExample6 { public static void main(String[] args) throws Exception { Test test = new Test(); long start = System.currentTimeMillis(); //调用同步方法1000000000L 来计算1000000000L的++,对比偏向锁和轻量级锁的性能 for(int i=0;i<1000000000L;i++){ test.parse(); } long end = System.currentTimeMillis(); System.out.println(String.format("%sms", end - start)); }}
![d2bcc5ea69f8569b797f53c602506a17.png](https://i-blog.csdnimg.cn/blog_migrate/20494a85b3ebc46376ee077fce8b048e.jpeg)
此时是轻量锁大概26秒,然后关闭偏向锁延迟再看看
![686f4a1afaf63999be984e38fd7a7e9d.png](https://i-blog.csdnimg.cn/blog_migrate/c417f973efc4aafae33858e99050383c.jpeg)
性能对比轻量锁和重量锁:
package org.xinhua.cbcloud.jol;import java.util.concurrent.CountDownLatch;public class JOLExample7 { static CountDownLatch countDownLatch = new CountDownLatch(1000000000); public static void main(String[] args) throws Exception { final Test test = new Test(); long start = System.currentTimeMillis(); //调用同步方法1000000000L 来计算1000000000L的++,对比偏向锁和轻量级锁的性能 for(int i=0; i<2; i++){ new Thread(){ @Override public void run() { while (countDownLatch.getCount() > 0) { test.parse(); } } }.start(); } countDownLatch.await(); long end = System.currentTimeMillis(); System.out.println(String.format("%sms", end - start)); }}
这里就不贴图了,我这个电脑简直慢到如法想象,大家可以自己测试一下。
注意一:如果调用wait方法则立刻变成重量锁
package org.xinhua.cbcloud.jol;import org.openjdk.jol.info.ClassLayout;import static java.lang.System.out;// 如果调用wait方法则立刻变成重量锁public class JOLExample8 { static Test test; public static void main(String[] args) throws Exception { //Thread.sleep(5000); test = new Test(); out.println("befre lock"); out.println(ClassLayout.parseInstance(test).toPrintable()); Thread t1 = new Thread() { public void run() { synchronized (test) { try { synchronized (test) { System.out.println("before wait"); out.println(ClassLayout.parseInstance(test).toPrintable()); test.wait(); System.out.println(" after wait"); out.println(ClassLayout.parseInstance(test).toPrintable()); } } catch (InterruptedException e) { e.printStackTrace(); } } } }; t1.start(); Thread.sleep(5000); synchronized (test) { test.notifyAll(); } } public static void sync() throws InterruptedException { synchronized (test) { System.out.println("t1 main lock"); out.println(ClassLayout.parseInstance(test).toPrintable()); } }}
![6d3f315bce1121eccfbf127b7cdf0e62.png](https://i-blog.csdnimg.cn/blog_migrate/34fca5e00a62db6856466e66071f253f.jpeg)
注意一:如果对象已经计算了hashcode就不能偏向了
package org.xinhua.cbcloud.jol;import org.openjdk.jol.info.ClassLayout;import static java.lang.System.out;// 如果对象已经计算了hashcode就不能偏向了public class JOLExample9 { static Test test; public static void main(String[] args) throws Exception { Thread.sleep(5000); test = new Test(); test.hashCode(); out.println("befor lock"); out.println(ClassLayout.parseInstance(test).toPrintable()); synchronized (test){ out.println("lock ing"); out.println(ClassLayout.parseInstance(test).toPrintable()); } out.println("after lock"); out.println(ClassLayout.parseInstance(test).toPrintable()); }}
![770baeef9f2421cf8debc4793efd2baf.png](https://i-blog.csdnimg.cn/blog_migrate/35daa04265d0b10993603ae76d217fe3.jpeg)
本章总结
本章简单对锁的性能进行了测试,目的是让大家的编码的过程中有意识的注意锁的转换过程,可能直接对你的程序运行结果产生一定的影响,一定要自己亲自动手测试才能加深印象。下篇会通过编译linux源码来深入理解synchronized的原理。