/** * 案例测试 * 堆代码 duidaima.com */ public class LockDemo { private static Lock lock = new ReentrantLock(); private static int num1 = 0; private static int num2 = 0; public static void main(String[] args) { lockDemo(); SyncDemo(); } /** * 本机测试下20万自增基本能确定性能,但是不是特别明显,50万差距还是挺大的 * 20万以下数据synchronized优于Lock * 20万以上数据Lock优于synchronized */ public static void lockDemo(){ long start = System.currentTimeMillis(); for(int i=0;i<500000;i++){ final int num = i; new Runnable() { @Override public void run() { lock(num); } }.run(); } long end = System.currentTimeMillis(); System.out.println("累加:"+num1); System.out.println("ReentrantLock锁:"+ (end-start)); } public static void SyncDemo(){ long start = System.currentTimeMillis(); for(int i=0;i<500000;i++){ final int num = i; new Runnable() { @Override public void run() { sync(num); } }.run(); } long end = System.currentTimeMillis(); System.out.println("累加:"+num2); System.out.println("synchronized锁:"+ (end-start)); } public static void lock(int i){ lock.lock(); num1 ++; lock.unlock(); } public static synchronized void sync(int i){ num2 ++; } }50万++测试数据:
累加:500000 ReentrantLock锁:20 累加:500000 synchronized锁:28用数据说话,很明显在高并发下,ReentrantLock 的性能是要优于 synchronized 的,虽然仅仅是几毫秒的差距,当然这里我并没有对比CPU的使用情况。
累加:100000 ReentrantLock锁:13 累加:100000 synchronized锁:8
在JDK 1.6之后,虚拟机对于synchronized关键字进行整体优化后,在性能上synchronized与ReentrantLock已没有明显差距,因此在使用选择上,需要根据场景而定,大部分情况下我们依然建议是synchronized关键字,原因之一是使用方便语义清晰,二是性能上虚拟机已为我们自动优化。
而ReentrantLock提供了多样化的同步特性,如超时获取锁、可以被中断获取锁(synchronized的同步是不能中断的)、等待唤醒机制的多个条件变量(Condition)等,因此当我们确实需要使用到这些功能是,可以选择ReentrantLock