莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          ReentrantLock和內部鎖的性能對比(update)

          Posted on 2007-09-14 17:15 dennis 閱讀(8128) 評論(2)  編輯  收藏 所屬分類: java
              ReentrantLock是jdk5引入的新的鎖機制,它與內部鎖(synchronize) 相同的并發性和內存語義,比如可重入加鎖語義。在中等或者更高負荷下,ReentrantLock有更好的性能,并且擁有可輪詢和可定時的請求鎖等高級功能。這個程序簡單對比了ReentrantLock公平鎖、ReentrantLock非公平鎖以及內部鎖的性能,從結果上看,非公平的ReentrantLock表現最好。內部鎖也僅僅是實現統計意義上的公平,結果也比公平的ReentrantLock好上很多。這個程序僅僅是計數,啟動N個線程,對同一個Counter進行遞增,顯然,這個遞增操作需要同步以保證原子性,采用不同的鎖來實現同步,然后查看結果。
          Counter接口:
          package net.rubyeye.concurrency.chapter13;

          public interface Counter {
              
          public long getValue();

              
          public void increment();

          }

          然后,首先使用我們熟悉的synchronize來實現同步:
          package net.rubyeye.concurrency.chapter13;

          public class SynchronizeBenchmark implements Counter {
              
          private long count = 0;

              
          public long getValue() {
                  
          return count;
              }

              
          public synchronized void increment() {
                  count
          ++;
              }
          }

          采用ReentrantLock的版本,切記要在finally中釋放鎖,這是與synchronize使用方式最大的不同,內部鎖jvm會自動幫你釋放鎖,而ReentrantLock需要你自己來處理。
          package net.rubyeye.concurrency.chapter13;

          import java.util.concurrent.locks.Lock;
          import java.util.concurrent.locks.ReentrantLock;

          public class ReentrantLockBeanchmark implements Counter {

              
          private volatile long count = 0;

              
          private Lock lock;

              
          public ReentrantLockBeanchmark() {
                  
          // 使用非公平鎖,true就是公平鎖
                  lock = new ReentrantLock(false);
              }

              
          public long getValue() {
                  
          // TODO Auto-generated method stub
                  return count;
              }

              
          public void increment() {
                  lock.lock();
                  
          try {
                      count
          ++;
                  } 
          finally {
                      lock.unlock();
                  }
              }

          }

              寫一個測試程序,使用CyclicBarrier來等待所有任務線程創建完畢以及所有任務線程計算完成,清單如下:
          package net.rubyeye.concurrency.chapter13;

          import java.util.concurrent.CyclicBarrier;

          public class BenchmarkTest {
              
          private Counter counter;

              
          private CyclicBarrier barrier;

              
          private int threadNum;

              
          public BenchmarkTest(Counter counter, int threadNum) {
                  
          this.counter = counter;
                  barrier 
          = new CyclicBarrier(threadNum + 1); //關卡計數=線程數+1
                  this.threadNum = threadNum;
              }

              
          public static void main(String args[]) {
                  
          new BenchmarkTest(new SynchronizeBenchmark(), 5000).test();
                 
          //new BenchmarkTest(new ReentrantLockBeanchmark(), 5000).test();
                  //new BenchmarkTest(new ReentrantLockBeanchmark(), 5000).test();   
              }

              
          public void test() {
                  
          try {
                      
          for (int i = 0; i < threadNum; i++) {
                          
          new TestThread(counter).start();
                      }
                     
          long start = System.currentTimeMillis();
                      barrier.await(); // 等待所有任務線程創建
                      barrier.await(); // 等待所有任務計算完成
                      long end = System.currentTimeMillis();
                      System.out.println(
          "count value:" + counter.getValue());
                      System.out.println(
          "花費時間:" + (end - start) + "毫秒");
                  } 
          catch (Exception e) {
                      
          throw new RuntimeException(e);
                  }
              }

              
          class TestThread extends Thread {
                  
          private Counter counter;

                  
          public TestThread(final Counter counter) {
                      
          this.counter = counter;
                  }

                  
          public void run() {
                      
          try {
                          barrier.await();
                          
          for (int i = 0; i < 100; i++)
                              counter.increment();
                          barrier.await();
                      } 
          catch (Exception e) {
                          
          throw new RuntimeException(e);
                      }
                  }
              }
          }

          分別測試一下,

          將啟動的線程數限定為500,結果為:
          公平ReentrantLock:      210 毫秒
          非公平ReentrantLock :   39  毫秒
          內部鎖:                          39 毫秒

          將啟動的線程數限定為1000,結果為:
          公平ReentrantLock:      640 毫秒
          非公平ReentrantLock :   81 毫秒
          內部鎖:                           60 毫秒

          線程數不變,test方法中的循環增加到1000次,結果為:
          公平ReentrantLock:      16715 毫秒
          非公平ReentrantLock :   168 毫秒
          內部鎖:                           639  毫秒

          將啟動的線程數增加到2000,結果為:
          公平ReentrantLock:      1100 毫秒
          非公平ReentrantLock:   125 毫秒
          內部鎖:                           130 毫秒

          將啟動的線程數增加到3000,結果為:
          公平ReentrantLock:      2461 毫秒
          非公平ReentrantLock:   254 毫秒
          內部鎖:                           307 毫秒

          啟動5000個線程,結果如下:
          公平ReentrantLock:      6154  毫秒
          非公平ReentrantLock:   623   毫秒
          內部鎖:                           720 毫秒

          非公平ReentrantLock和內部鎖的差距,在jdk6上應該縮小了,據說jdk6的內部鎖機制進行了調整。

          評論

          # re: ReentrantLock和內部鎖的性能對比  回復  更多評論   

          2007-09-15 09:26 by 千里冰封
          JDK6比起JDK5確實又有些進步了,SUN公司就是牛,JAVA是越來越強大了,哈哈

          # re: ReentrantLock和內部鎖的性能對比(update)  回復  更多評論   

          2007-09-17 08:46 by dennis
          @千里冰封
          java在并發方面經過5,6兩個版本確實已經相當強大
          主站蜘蛛池模板: 汶川县| 潞西市| 巴楚县| 永和县| 霍林郭勒市| 新巴尔虎右旗| 镶黄旗| 双柏县| 桑日县| 玉环县| 隆安县| 凤山市| 抚顺县| 福清市| 济南市| 宁都县| 松滋市| 洪湖市| 长葛市| 珲春市| 怀仁县| 新竹县| 蓬安县| 广饶县| 阿荣旗| 关岭| 柳州市| 忻州市| 类乌齐县| 青州市| 安多县| 临安市| 仁化县| 托里县| 龙口市| 项城市| 永顺县| 米易县| 龙里县| 花莲市| 庆阳市|