ReentrantLock和synchronized的性能_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > ReentrantLock和synchronized的性能

ReentrantLock和synchronized的性能

 2012/2/15 9:08:43  495081611  程序员俱乐部  我要评论(0)
  • 摘要:转载http://my.oschina.net/digerl/blog/33282为了比较一下ReentrantLock和synchronized的性能,做了一下性能测试:得出结论:(1)使用Lock的性能比使用synchronized关键字要提高4~5倍;(2)使用信号量实现同步的速度大约比synchronized要慢10~20%;(3)使用atomic包的AtomicInter速度是比Lock要快1一个数量级。ReentrantLock类java.util.concurrent
  • 标签:Ron Ant
转载 http://my.oschina.net/digerl/blog/33282

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

得出结论:

(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的源码

view plaincopy to clipboardprint?
01.public abstract class Test {  
02.    protected String id;  
03.    protected CyclicBarrier barrier;  
04.    protected long count;  
05.    protected int threadNum;  
06.    protected ExecutorService executor;  
07. 
08.    public Test(String id, CyclicBarrier barrier, long count, int threadNum,  
09.            ExecutorService executor) {  
10.        this.id = id;  
11.        this.barrier = barrier;  
12.        this.count = count;  
13.        this.threadNum = threadNum;  
14.        this.executor = executor;  
15.    }  
16. 
17.    public void startTest() {  
18. 
19.        long start = System.currentTimeMillis();  
20. 
21.        for (int j = 0; j < threadNum; j++) {  
22.            executor.execute(new Thread() {  
23.                @Override 
24.                public void run() {  
25.                    for (int i = 0; i < count; i++) {  
26.                        test();  
27.                    }  
28. 
29.                    try {  
30.                        barrier.await();  
31. 
32.                    } catch (InterruptedException e) {  
33.                        e.printStackTrace();  
34.                    } catch (BrokenBarrierException e) {  
35.                        e.printStackTrace();  
36.                    }  
37.                }  
38.            });  
39.        }  
40. 
41.        try {  
42.            barrier.await();  
43.        } catch (InterruptedException e) {  
44.            e.printStackTrace();  
45.        } catch (BrokenBarrierException e) {  
46.            e.printStackTrace();  
47.        }  
48. 
49.        // 所有线程执行完成之后,才会跑到这一步  
50.        long duration = System.currentTimeMillis() - start;  
51.        System.out.println(id + " = " + duration);  
52.    }  
53. 
54.    protected abstract void test();  
55.} 
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 源码


view plaincopy to clipboardprint?
01.import thread.test.Test;  
02. 
03.public class ReentreLockTest {  
04.    private static long COUNT = 1000000;  
05.    private static Lock lock = new ReentrantLock();  
06.    private static long lockCounter = 0;  
07.    private static long syncCounter = 0;  
08.    private static long semaCounter = 0;  
09.    private static AtomicLong atomicCounter = new AtomicLong(0);  
10.    private static Object syncLock = new Object();  
11.    private static Semaphore mutex = new Semaphore(1);  
12. 
13.    public static void testLock(int num, int threadCount) {  
14. 
15.    }  
16. 
17.    static long getLock() {  
18.        lock.lock();  
19.        try {  
20.            return lockCounter;  
21.        } finally {  
22.            lock.unlock();  
23.        }  
24.    }  
25. 
26.    static long getSync() {  
27.        synchronized (syncLock) {  
28.            return syncCounter;  
29.        }  
30.    }  
31. 
32.    static long getAtom() {  
33.        return atomicCounter.get();  
34.    }  
35. 
36.    static long getSemaphore() throws InterruptedException {  
37.        mutex.acquire();  
38. 
39.        try {  
40.            return semaCounter;  
41.        } finally {  
42.            mutex.release();  
43.        }  
44.    }  
45. 
46.    static long getLockInc() {  
47.        lock.lock();  
48.        try {  
49.            return ++lockCounter;  
50.        } finally {  
51.            lock.unlock();  
52.        }  
53.    }  
54. 
55.    static long getSyncInc() {  
56.        synchronized (syncLock) {  
57.            return ++syncCounter;  
58.        }  
59.    }  
60. 
61.    static long getAtomInc() {  
62.        return atomicCounter.getAndIncrement();  
63.    }  
64. 
65.    static class SemaTest extends Test {  
66. 
67.        public SemaTest(String id, CyclicBarrier barrier, long count,  
68.                int threadNum, ExecutorService executor) {  
69.            super(id, barrier, count, threadNum, executor);  
70.        }  
71. 
72.        @Override 
73.        protected void test() {  
74.            try {  
75.                getSemaphore();  
76.            } catch (InterruptedException e) {  
77.                e.printStackTrace();  
78.            }  
79.        }  
80. 
81.    }  
82. 
83.    static class LockTest extends Test {  
84. 
85.        public LockTest(String id, CyclicBarrier barrier, long count,  
86.                int threadNum, ExecutorService executor) {  
87.            super(id, barrier, count, threadNum, executor);  
88.        }  
89. 
90.        @Override 
91.        protected void test() {  
92.            getLock();  
93.        }  
94. 
95.    }  
96. 
97.    static class SyncTest extends Test {  
98. 
99.        public SyncTest(String id, CyclicBarrier barrier, long count,  
100.                int threadNum, ExecutorService executor) {  
101.            super(id, barrier, count, threadNum, executor);  
102.        }  
103. 
104.        @Override 
105.        protected void test() {  
106.            getSync();  
107.        }  
108. 
109.    }  
110. 
111.    static class AtomicTest extends Test {  
112. 
113.        public AtomicTest(String id, CyclicBarrier barrier, long count,  
114.                int threadNum, ExecutorService executor) {  
115.            super(id, barrier, count, threadNum, executor);  
116.        }  
117. 
118.        @Override 
119.        protected void test() {  
120.            getAtom();  
121.        }  
122. 
123.    }  
124. 
125.    public static void test(String id, long count, int threadNum,  
126.            ExecutorService executor) {  
127. 
128.        final CyclicBarrier barrier = new CyclicBarrier(threadNum + 1,  
129.                new Thread() {  
130. 
131.                    @Override 
132.                    public void run() {  
133. 
134.                    }  
135.                });  
136. 
137.        System.out.println("==============================");  
138.        System.out.println("count = " + count + "\t" + "Thread Count = " 
139.                + threadNum);  
140. 
141.        new LockTest("Lock ", barrier, COUNT, threadNum, executor).startTest();  
142.        new SyncTest("Sync ", barrier, COUNT, threadNum, executor).startTest();  
143.        new AtomicTest("Atom ", barrier, COUNT, threadNum, executor)  
144.                .startTest();  
145.        new SemaTest("Sema ", barrier, COUNT, threadNum, executor)  
146.                .startTest();  
147.        System.out.println("==============================");  
148.    }  
149. 
150.    public static void main(String[] args) {  
151.        for (int i = 1; i < 5; i++) {  
152.            ExecutorService executor = Executors.newFixedThreadPool(10 * i);  
153.            test("", COUNT * i, 10 * i, executor);  
154.        }  
155.    }  
156.} 
import thread.test.Test;

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);
  }
}
}


结果

view plaincopy to clipboardprint?
01.==============================  
02.count = 1000000 Thread Count = 10  
03.Lock  = 953  
04.Sync  = 3781  
05.Atom  = 78  
06.Sema  = 4922  
07.==============================  
08.==============================  
09.count = 2000000 Thread Count = 20  
10.Lock  = 1906  
11.Sync  = 8469  
12.Atom  = 172  
13.Sema  = 9719  
14.==============================  
15.==============================  
16.count = 3000000 Thread Count = 30  
17.Lock  = 2890  
18.Sync  = 12641  
19.Atom  = 219  
20.Sema  = 15015  
21.==============================  
22.==============================  
23.count = 4000000 Thread Count = 40  
24.Lock  = 3844  
25.Sync  = 17141  
26.Atom  = 343  
27.Sema  = 19782  
28.==============================
发表评论
用户名: 匿名