檢測synchronized與ReentrantLock效能差異
在java併發程式設計實戰中說synchronized與ReentrantLock效能從java1.6以後基本持平,並且網上也有人這樣說,然後我就用程式測試一下,測試環境jdk1.8 ,cpu i5-4210H,程式碼如下:
public class LockPerformanceTest {
static int threadCount = 8;
public static void main(String[] args) throws InterruptedException {
testReentrantLock();
Thread.sleep(1000);
testSynchronized();
}
private static void testSynchronized() {
List<Thread> threads = new ArrayList<>();
AtomicBoolean breakTag = new AtomicBoolean(false);
HashSet<String> set = new HashSet<String>();
final AtomicLong counter = new AtomicLong();
String val = "1";
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread() {
public void run() {
this.setPriority(NORM_PRIORITY);
while (!breakTag.get()) {
synchronized (set) {
set.contains(val);
}
counter.incrementAndGet();
}
}
};
threads.add(t);
t.start();
}
Thread t= new Thread() {
public void run() {
this.setPriority(NORM_PRIORITY);
long lastCount = counter.get();
int loop = 0;
long total = 0;
while (true) {
long tempCount = counter.get() - lastCount;
total += tempCount;
lastCount = counter.get();
loop++;
if (loop >= 5) {
System.out
.println("Synchronized平均處理個數:" + total / loop);
breakTag.set(true);
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
threads.add(t);
t.start();
for(Thread th : threads){
try {
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static void testReentrantLock() {
List<Thread> threads = new ArrayList<>();
AtomicBoolean breakTag = new AtomicBoolean(false);
HashSet<String> set = new HashSet<String>();
final AtomicLong counter = new AtomicLong();
ReentrantLock lock = new ReentrantLock();
String val = "1";
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread() {
public void run() {
this.setPriority(NORM_PRIORITY);
while (!breakTag.get()) {
lock.lock();
try {
set.contains(val);
} finally {
lock.unlock();
}
counter.incrementAndGet();
}
}
};
threads.add(t);
t.start();
}
Thread t= new Thread() {
public void run() {
this.setPriority(NORM_PRIORITY);
long lastCount = counter.get();
int loop = 0;
long total = 0;
while (true) {
long tempCount = counter.get() - lastCount;
total += tempCount;
lastCount = counter.get();
loop++;
if (loop >= 5) {
System.out.println("ReentrantLock平均處理個數:" + total
/ loop);
breakTag.set(true);
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
threads.add(t);
t.start();
for(Thread th : threads){
try {
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
最後測試結果如下:線上程個數是1個的時候,效能差不多;2個時synchronized > ReentrantLock;2個以上ReentrantLock > synchronized,並且效能差距有0.5倍左右。所以在對效能要求不是很高的情況下還是用synchronized,畢竟使用方便,ReentrantLock在對效能有較高要求時使用,並且靈活性高,但是容易程式設計出錯,萬一忘了在finally中釋放鎖將造成死鎖。