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
这个结果算是正常的结果了。
总结:
- 以前一直听说JVM可以在运行时优化代码,果然是相当的牛B的功能,直接在运行时把无用的代码全优化掉了。
- 测试程序要注意防止jvm等的优化
- ReentrantLock和synchronize在单线程下效率基本一样(从实现原理来看,在单线程情况下,都是一个比较指令即可)
- 在单线程下,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();
}
}
}
AI 代码解读
加上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();
}
}
}
AI 代码解读