各類同步方法性能比較(synchronized,ReentrantLock,Atomic)

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

得出結論:算法

(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 能夠花更少的時候來調度線程,把更多時間用在執行線程上。) ide

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

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

  Test的源碼ui

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;this

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

相關文章
相關標籤/搜索