synchronizedとLockの2種類のロックの性能テストと比較
この2つのロックについてjdk 1である.6以前のsynchronizedの性能はロックに及ばなかった.synchronizedはオペレーティングシステムの関数を呼び出す必要があるため、オペレーティングカーネルが完成し、JDK 1で比較的時間がかかる.6以降、Oracle社はsynchronizedを大量に最適化し、偏向ロック、スピンロックなどのjvmレベルのロックメカニズムを導入し、性能を大幅に向上させ、JDK 1が一般的に使用されている.8の今、好奇心から、私は簡単にsynchronizedとLockをJDK 1でテストしました.2つの間のパフォーマンスを8回実行します.
単一スレッドでsynchronizedとLockを使用してそれぞれ100回0~100万の重ね合わせ操作を行います.この場合、ロック解除を100回繰り返します.テストコードは以下の通りです.
結果(各3回の結果を取る):
単一スレッドの場合、synchronizedの性能はLockより優れ、synchronizedのロック解除ロック速度はLockより速いことがわかる.
10スレッドでsynchronizedとlockをそれぞれ100回使用して0~100万のオーバーラップ操作を行い、10回ロックを競合します.テストコードは以下の通りです.
結果(各3回の結果を取る):
上記と同じコードロジックで、スレッド数を1000に調整し、以下の結果を得た(各3回の結果を取る):
最後に,スレッド数を1万に調整し,以下の結果を得た(各3回の結果をとる).
今回のテストは簡単ですが、jdk 1も基本的に見ることができます.8バージョンでは、synchronizedとLockのパフォーマンスは1万個以内であまり変わらないが、これらのテストデータは私がノートパソコンを使ってテストしたもので、簡単な参考になるだけだ.
単一スレッドでsynchronizedとLockを使用してそれぞれ100回0~100万の重ね合わせ操作を行います.この場合、ロック解除を100回繰り返します.テストコードは以下の通りです.
public class Test2 {
private static Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
function1();
}
System.out.println(" ,synchronized :" + (System.currentTimeMillis() - start));
/*long start2 = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
function2();
}
System.out.println(" ,Lock :" + (System.currentTimeMillis() - start2));*/
}
/**
* synchronized 1-100
*/
public synchronized static void function1() {
int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += i;
}
}
/**
* Lock 1-100
*/
public static void function2() {
lock.lock();
int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += i;
}
lock.unlock();
}
}
結果(各3回の結果を取る):
,synchronized :6
,synchronized :5
,synchronized :5
,Lock :35
,Lock :35
,Lock :35
単一スレッドの場合、synchronizedの性能はLockより優れ、synchronizedのロック解除ロック速度はLockより速いことがわかる.
10スレッドでsynchronizedとlockをそれぞれ100回使用して0~100万のオーバーラップ操作を行い、10回ロックを競合します.テストコードは以下の通りです.
/*----------------------------------------------------*/
/*-------------------- -------------------------*/
/*----------------------------------------------------*/
public class Test {
//
private static int threadCounts = 10;
// ,
public static CountDownLatch latch = new CountDownLatch(threadCounts);
//
public static CyclicBarrier cyc = new CyclicBarrier(threadCounts + 1);
public static void main(String[] args) {
List<Thread> threads1 = new ArrayList<>();
for (int i = 0; i < threadCounts; i++) {
Thread thread = new Thread(new SyncTest());
threads1.add(thread);
thread.start();
latch.countDown();
}
long start = System.currentTimeMillis();
try {
Test.cyc.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(threadCounts+" ,synchronized :"+(System.currentTimeMillis()-start));
/*--------------------- lock, , --------------------------*/
/*Lock lock = new ReentrantLock();
List threads = new ArrayList<>();
for (int i = 0; i < threadCounts; i++) {
Thread thread = new Thread(new LockTest(lock));
threads.add(thread);
thread.start();
latch.countDown();
}
long start2 = System.currentTimeMillis();
try {
Test.cyc.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(threadCounts + " ,lock :" + (System.currentTimeMillis() - start2));*/
}
}
/**
* synchronized Runnable
*/
class SyncTest implements Runnable {
@Override
public void run(){
try {
Test.latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (SyncTest.class) {
for (int i = 0; i < 100; i++) {
function();
}
Test.i++;
}
try {
Test.cyc.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public void function() {
int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += i;
}
}
}
/**
* Lock Runnable
*/
class LockTest implements Runnable {
private Lock lock;
public LockTest(Lock lock) {
this.lock = lock;
}
@Override
public void run() {
try {
Test.latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
for (int i = 0; i < 100; i++) {
function();
}
lock.unlock();
try {
Test.cyc.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public void function() {
int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += i;
}
}
}
結果(各3回の結果を取る):
10 ,synchronized :5
10 ,synchronized :5
10 ,synchronized :5
10 ,lock :5
10 ,lock :5
10 ,lock :5
上記と同じコードロジックで、スレッド数を1000に調整し、以下の結果を得た(各3回の結果を取る):
1000 ,synchronized :72
1000 ,synchronized :60
1000 ,synchronized :67
1000 ,lock :82
1000 ,lock :85
1000 ,lock :83
最後に,スレッド数を1万に調整し,以下の結果を得た(各3回の結果をとる).
10000 ,synchronized :6613
10000 ,synchronized :7619
10000 ,synchronized :7063
10000 ,lock :7310
10000 ,lock :7257
10000 ,lock :7905
今回のテストは簡単ですが、jdk 1も基本的に見ることができます.8バージョンでは、synchronizedとLockのパフォーマンスは1万個以内であまり変わらないが、これらのテストデータは私がノートパソコンを使ってテストしたもので、簡単な参考になるだけだ.