比較ReentrantLock和synchronized和信號量Semaphore實現的同步性能

爲了比較一下ReentrantLock和synchronized的性能,作了一下性能測試: java

參考http://my.oschina.net/leoson/blog/107327 算法

得出結論: 多線程

(1)使用Lock的性能比使用synchronized關鍵字要提升4~5倍; 併發

(2)使用信號量實現同步的速度大約比synchronized要慢10~20%; 框架

(3)使用atomic包的AtomicInter速度是比Lock要快1一個數量級。 ide

ReentrantLock 類
java.util.concurrent.lock 中的 Lock 框架是鎖定的一個抽象,它容許把鎖定的實現做爲 Java 類,而不是做爲語言的特性來實現。這就爲 Lock 的多種實現留下了空間,各類實現可能有不一樣的調度算法、性能特性或者鎖定語義。ReentrantLock 類實現了 Lock,它擁有與 synchronized 相同的併發性和內存語義,可是添加了相似鎖投票、定時鎖等候和可中斷鎖等候的一些特性。此外,它還提供了在激烈爭用狀況下更佳的性能。(換句話說,當許多線程都想訪問共享資源時,JVM 能夠花更少的時候來調度線程,把更多時間用在執行線程上。) 性能

reentrant 鎖意味着什麼呢?簡單來講,它有一個與鎖相關的獲取計數器,若是擁有鎖的某個線程再次獲得鎖,那麼獲取計數器就加1,而後鎖須要被釋放兩次才能得到真正釋放。這模仿了 synchronized 的語義;若是線程進入由線程已經擁有的監控器保護的 synchronized 塊,就容許線程繼續進行,當線程退出第二個(或者後續)synchronized 塊的時候,不釋放鎖,只有線程退出它進入的監控器保護的第一個 synchronized 塊時,才釋放鎖。 測試

在查看清單 1 中的代碼示例時,能夠看到 Lock 和 synchronized 有一點明顯的區別 —— lock 必須在 finally 塊中釋放。不然,若是受保護的代碼將拋出異常,鎖就有可能永遠得不到釋放!這一點區別看起來可能沒什麼,可是實際上,它極爲重要。忘記在 finally 塊中釋放鎖,可能會在程序中留下一個定時bomb,當有一天bomb爆炸時,您要花費很大力氣纔有找到源頭在哪。而使用同步,JVM 將確保鎖會得到自動釋放。 ui

  Test的源碼: this

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;

public abstract class Test {
	protected String id;
	protected CyclicBarrier barrier;
	protected long count;
	protected int threadNum;
	protected ExecutorService executor;

	public Test(String id, CyclicBarrier barrier, long count, int threadNum,
			ExecutorService executor) {
		this.id = id;
		this.barrier = barrier;
		this.count = count;
		this.threadNum = threadNum;
		this.executor = executor;
	}

	public void startTest() {

		long start = System.currentTimeMillis();

		for (int j = 0; j < threadNum; j++) {
			executor.execute(new Thread() {
//				@Override
				public void run() {
					for (int i = 0; i < count; i++) {
						test();
					}

					try {
						barrier.await();

					} catch (InterruptedException e) {
						e.printStackTrace();
					} catch (BrokenBarrierException e) {
						e.printStackTrace();
					}
				}
			});
		}

		try {
			barrier.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}

		// 全部線程執行完成以後,纔會跑到這一步
		long duration = System.currentTimeMillis() - start;
		System.out.println(id + " = " + duration);
	}

	protected abstract void test();
}

 

測試類ReentreLockTest 源碼: 

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class ReentreLockTest {
	private static long COUNT = 1000000;
	private static Lock lock = new ReentrantLock();
	private static long lockCounter = 0;
	private static long syncCounter = 0;
	private static long semaCounter = 0;
	private static AtomicLong atomicCounter = new AtomicLong(0);
	private static Object syncLock = new Object();
	private static Semaphore mutex = new Semaphore(1);

	public static void testLock(int num, int threadCount) {

	}

	static long getLock() {
		lock.lock();
		try {
			return lockCounter;
		} finally {
			lock.unlock();
		}
	}

	static long getSync() {
		synchronized (syncLock) {
			return syncCounter;
		}
	}

	static long getAtom() {
		return atomicCounter.get();
	}

	static long getSemaphore() throws InterruptedException {
		mutex.acquire();

		try {
			return semaCounter;
		} finally {
			mutex.release();
		}
	}

	static long getLockInc() {
		lock.lock();
		try {
			return ++lockCounter;
		} finally {
			lock.unlock();
		}
	}

	static long getSyncInc() {
		synchronized (syncLock) {
			return ++syncCounter;
		}
	}

	static long getAtomInc() {
		return atomicCounter.getAndIncrement();
	}

	static class SemaTest extends Test {

		public SemaTest(String id, CyclicBarrier barrier, long count,
				int threadNum, ExecutorService executor) {
			super(id, barrier, count, threadNum, executor);
		}

		@Override
		protected void test() {
			try {
				getSemaphore();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	static class LockTest extends Test {

		public LockTest(String id, CyclicBarrier barrier, long count,
				int threadNum, ExecutorService executor) {
			super(id, barrier, count, threadNum, executor);
		}

		@Override
		protected void test() {
			getLock();
		}

	}

	static class SyncTest extends Test {

		public SyncTest(String id, CyclicBarrier barrier, long count,
				int threadNum, ExecutorService executor) {
			super(id, barrier, count, threadNum, executor);
		}

		@Override
		protected void test() {
			getSync();
		}

	}

	static class AtomicTest extends Test {

		public AtomicTest(String id, CyclicBarrier barrier, long count,
				int threadNum, ExecutorService executor) {
			super(id, barrier, count, threadNum, executor);
		}

		@Override
		protected void test() {
			getAtom();
		}

	}

	public static void test(String id, long count, int threadNum,
			ExecutorService executor) {

		final CyclicBarrier barrier = new CyclicBarrier(threadNum + 1,
				new Thread() {

					@Override
					public void run() {

					}
				});

		System.out.println("==============================");
		System.out.println("count = " + count + "/t" + "Thread Count = "
				+ threadNum);

		new LockTest("Lock ", barrier, COUNT, threadNum, executor).startTest();
		new SyncTest("Sync ", barrier, COUNT, threadNum, executor).startTest();
		new AtomicTest("Atom ", barrier, COUNT, threadNum, executor)
				.startTest();
		new SemaTest("Sema ", barrier, COUNT, threadNum, executor)
				.startTest();
		System.out.println("==============================");
	}

	public static void main(String[] args) {
		for (int i = 1; i < 5; i++) {
			ExecutorService executor = Executors.newFixedThreadPool(10 * i);
			test("", COUNT * i, 10 * i, executor);
		}
	}
}

 

結果:
==============================
count = 1000000/tThread Count = 10
Lock  = 417
Sync  = 1876
Atom  = 34
Sema  = 3749
==============================
==============================
count = 2000000/tThread Count = 20
Lock  = 815
Sync  = 3480
Atom  = 69
Sema  = 7448
==============================
==============================
count = 3000000/tThread Count = 30
Lock  = 1234
Sync  = 5163
Atom  = 93
Sema  = 10609
==============================
==============================
count = 4000000/tThread Count = 40
Lock  = 1611
Sync  = 6934
Atom  = 142
Sema  = 13243
==============================

相關文章
相關標籤/搜索