测试Java的synchronize和ReentrantLock在单线程下的效率

原创 2012年06月14日 02:40:21

ReentrantLock 在多线程情况下要远胜synchronize,这点没有疑问。

最近要写个程序,有个变量是有多数情况下是一个线程读写,有少数情况下是多个线程并发读写。所以要测试下ReentrantLock 在单线程下和synchronize的效率对比。

在测试的过程中发现一个有意思的现象。

测试代码见后面。

测试代码1结果:

noLockTime: 0:00:00.004
noLockTime: 0:00:00.006
noLockTime: 0:00:00.000
syncTime: 0:00:02.902
syncTime: 0:00:02.902
syncTime: 0:00:02.886
ReentrantTime: 0:00:05.012
ReentrantTime: 0:00:05.007
ReentrantTime: 0:00:04.270

则开始看到这个测试结果,觉得相当奇怪,ReentrantLock居然比synchronize要慢这么多。

但是后来再仔细研究测试结果,发现原来是jvm把测试代码优化掉了!观察noLockTime的时间,差不多是0!

于是加上total的统计代码,得到以下的测试结果:

加上total统计的测试代码结果:

noLockTime: 0:00:03.786
total:1078760960
noLockTime: 0:00:03.774
total:1078760960
noLockTime: 0:00:03.428
total:1078760960
syncTime: 0:00:05.553
total:1078760960
syncTime: 0:00:05.555
total:1078760960
syncTime: 0:00:04.826
total:1078760960
ReentrantTime: 0:00:05.451
total:1078760960
ReentrantTime: 0:00:05.424
total:1078760960
ReentrantTime: 0:00:04.493
total:1078760960


这个结果算是正常的结果了。


总结:

  1. 以前一直听说JVM可以在运行时优化代码,果然是相当的牛B的功能,直接在运行时把无用的代码全优化掉了。
  2. 测试程序要注意防止jvm等的优化
  3. ReentrantLock和synchronize在单线程下效率基本一样(从实现原理来看,在单线程情况下,都是一个比较指令即可)
  4. 在单线程下,ReentrantLock和synchronize的效率是非常高的,一次调用约10e-11秒。


测试代码1:

import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.time.StopWatch;

public class XXX {
	static ReentrantLock lock = new ReentrantLock(false);
	static int size = 100;
	static int count = 100000000;
	
	static StopWatch watch = new StopWatch();
	public static void main(String[] args) {
		noLockTime();
		noLockTime();
		noLockTime();
		
		syncTime();
		syncTime();
		syncTime();
		
		ReentrantTime();
		ReentrantTime();
		ReentrantTime();
	}
	
	static void noLockTime(){
//		int total = 0;
		watch.reset();
		watch.start();
		for(int i = 0; i < count; ++i){
			testNotLock();
//			total += testNotLock();
		}
		watch.stop();
		System.out.println("noLockTime: " + watch);
//		System.out.println("total:" + total);
	}
	
	static void syncTime(){
//		int total = 0;
		watch.reset();
		watch.start();
		for(int i = 0; i < count; ++i){
			testSync();
//			total += testSync();
		}
		watch.stop();
		System.out.println("syncTime: " + watch);
//		System.out.println("total:" + total);
	}
	
	static void ReentrantTime(){
//		int total = 0;
		watch.reset();
		watch.start();
		for(int i = 0; i < count; ++i){
			testReentrantLock();
//			total += testReentrantLock();
		}
		watch.stop();
		System.out.println("ReentrantTime: " + watch);
//		System.out.println("total:" + total);
	}
	
	static int testNotLock(){
		int sum = 0;
		for(int i = 0; i < size; ++i){
			sum += i;
		}
		return sum;
	}
	
	static synchronized int testSync(){
		int sum = 0;
		for(int i = 0; i < size; ++i){
			sum += i;
		}
		return sum;
	}
	
	static int testReentrantLock(){
		try{
			lock.lock();
			int sum = 0;
			for(int i = 0; i < size; ++i){
				sum += i;
			}
			return sum;
		}finally{
			lock.unlock();
		}
	}
	
}



加上total统计的测试代码:

import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.time.StopWatch;

public class XXX {
	static ReentrantLock lock = new ReentrantLock(false);
	static int size = 100;
	static int count = 100000000;
	
	static StopWatch watch = new StopWatch();
	public static void main(String[] args) {
		noLockTime();
		noLockTime();
		noLockTime();
		
		syncTime();
		syncTime();
		syncTime();
		
		ReentrantTime();
		ReentrantTime();
		ReentrantTime();
	}
	
	static void noLockTime(){
		int total = 0;
		watch.reset();
		watch.start();
		for(int i = 0; i < count; ++i){
//			testNotLock();
			total += testNotLock();
		}
		watch.stop();
		System.out.println("noLockTime: " + watch);
		System.out.println("total:" + total);
	}
	
	static void syncTime(){
		int total = 0;
		watch.reset();
		watch.start();
		for(int i = 0; i < count; ++i){
//			testSync();
			total += testSync();
		}
		watch.stop();
		System.out.println("syncTime: " + watch);
		System.out.println("total:" + total);
	}
	
	static void ReentrantTime(){
		int total = 0;
		watch.reset();
		watch.start();
		for(int i = 0; i < count; ++i){
//			testReentrantLock();
			total += testReentrantLock();
		}
		watch.stop();
		System.out.println("ReentrantTime: " + watch);
		System.out.println("total:" + total);
	}
	
	static int testNotLock(){
		int sum = 0;
		for(int i = 0; i < size; ++i){
			sum += i;
		}
		return sum;
	}
	
	static synchronized int testSync(){
		int sum = 0;
		for(int i = 0; i < size; ++i){
			sum += i;
		}
		return sum;
	}
	
	static int testReentrantLock(){
		try{
			lock.lock();
			int sum = 0;
			for(int i = 0; i < size; ++i){
				sum += i;
			}
			return sum;
		}finally{
			lock.unlock();
		}
	}
	
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

synchronized和lock(reentrantlock) 区别

1.某个线程在等待一个锁的控制权的这段时间需要中断 2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程 3.具有公平锁...
  • ningguixin
  • ningguixin
  • 2014年04月17日 18:09
  • 6299

Java ReentrantLock和synchronize的对比

原文:http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新...
  • wangjianyu0115
  • wangjianyu0115
  • 2016年03月11日 14:13
  • 379

ReentrantLock和内部锁的性能对比

ReentrantLock是jdk5引入的新的锁机制,它与内部锁(synchronize) 相同的并发性和内存语义,比如可重入加锁语义。在中等或者更高负荷下,ReentrantLock有更好的性能,并...
  • chenglifan
  • chenglifan
  • 2012年05月04日 11:37
  • 740

各种同步方法性能比较(synchronized,ReentrantLock,Atomic)

5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类。了解其性能的优劣程度,有助与我们在特定的...
  • z69183787
  • z69183787
  • 2015年09月13日 21:06
  • 860

Java多线程并发编程之显示锁ReentrantLock和读写锁

在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 Reentr...
  • csujiangyu
  • csujiangyu
  • 2015年03月01日 14:10
  • 951

Java多线程之~~~Lock接口和ReentrantLock的使用

在多线程开发中,除了synchronized这个关键字外,我们还能通过Lock接口来实现这种效果。通过Lock接口来实现 这种多线程加锁效果的好处是非常的灵活,我们不在需要对整个函数加锁,而且可以很...
  • a352193394
  • a352193394
  • 2014年09月19日 22:29
  • 10307

synchronize和ReentrantLock

分别介绍synchronized和ReentrantLock的实现原理 1,synchronized实现原理 synchronized是jdk的内置锁,经过编译之后,会在同步块的前后形成monitor...
  • u013014724
  • u013014724
  • 2017年07月26日 14:54
  • 144

ReentrantLock.tryLock()方法简说

import java.util.concurrent.locks.ReentrantLock; public static ReentrantLock smsLock = new Reentr...
  • mingliangniwo
  • mingliangniwo
  • 2015年10月21日 18:25
  • 1430

Java并发编程:volatile关键字解析。以及volatile和synchronize的区别

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意...
  • xiaaiwu
  • xiaaiwu
  • 2016年09月03日 11:19
  • 1095

Java Synchronize 和 Lock 的区别与用法

ava语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。      一、当两个并发线程访问同一个对象object中的这个synchroniz...
  • itsoftchenfei
  • itsoftchenfei
  • 2014年04月02日 17:04
  • 1532
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:测试Java的synchronize和ReentrantLock在单线程下的效率
举报原因:
原因补充:

(最多只允许输入30个字)