比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能

为了比较一下ReentrantLock和synchronized的性能,做了一下性能测试:

参考http://my.oschina.net/leoson/blog/107327

得出结论:

(1)使用Lock的性能比使用synchronized关键字要提高4~5倍;

(2)使用信号量实现同步的速度大约比synchronized要慢10~20%;

(3)使用atomic包的AtomicInter速度是比Lock要快1一个数量级。

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 将确保锁会获得自动释放。

  Test的源码:

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
==============================

 

转载于:https://my.oschina.net/leoson/blog/107125

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值