1. 程式人生 > >一道面試題比較synchronized和讀寫鎖

一道面試題比較synchronized和讀寫鎖

  1. 用第一種方法處理,整個過程比較粗線條,程式碼比較簡單單執行效率很低。這種方法的中心思想是不管你是什麼操作,但凡涉及到公共資源就都給你同步。這麼做可以是可以但是並不好。
  2. 第二種用讀寫鎖處理顯然是對前者的一個優化,對第二種方法做如下幾點說明:
  • 關於unlock操作,我們知道只要是上了鎖就必須要解鎖,但是有這麼一種情況就是當你上完鎖後在執行解鎖操作前程式出現異常,那這個所可能就一直存在。所以針對這個問題我們一般將unlock操作放在finally程式碼塊中,就可以保證上了的鎖一定會被解。
  • 上面的兩次if判斷,第一個if相信大家很好理解。但為什麼要用第二個if呢?再假設一個場景,現在有十個執行緒來讀這個資料,而這個資料又不存在與快取區,那麼這十個執行緒中最先到的執行緒將執行“rw.writeLock().lock();”而另外九個執行緒將被阻塞,當第一個執行緒讀完以後快取區實際上已經就有了這個資料,但另外九個阻塞在
    “rw.writeLock().lock();”如果不加這層if他們會繼續訪問資料庫,由此可見加了這層if對整個過程影響很大。這是比較細節的一點,就這一點Java的API文件也考慮到了,它的樣例程式碼如下:
Java程式碼  
  1. class CachedData {  
  2.   Object data;  
  3.   volatileboolean cacheValid;  
  4.   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();  
  5.   void processCachedData() {  
  6.     rwl.readLock().lock();  
  7.     <span style="color: rgb(255, 0, 0);">if (!cacheValid)</span> {  
  8.        // Must release read lock before acquiring write lock
  9.        rwl.readLock().unlock();  
  10.        rwl.writeLock().lock();  
  11.        // Recheck state because another thread might have acquired
  12.        //   write lock and changed state before we did.
  13.       <span style="color: rgb(255, 0, 0);"if (!cacheValid)</span> {  
  14.          data = ...  
  15.          cacheValid = true;  
  16.        }  
  17.        // Downgrade by acquiring read lock before releasing write lock
  18.        rwl.readLock().lock();  
  19.        rwl.writeLock().unlock(); // Unlock write, still hold read
  20.     }  
  21.     use(data);  
  22.     rwl.readLock().unlock();  
  23.   }  
  24. }  
 class CachedData {
   Object data;
   volatile boolean cacheValid;
   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     if (!cacheValid) {
        // Must release read lock before acquiring write lock
        rwl.readLock().unlock();
        rwl.writeLock().lock();
        // Recheck state because another thread might have acquired
        //   write lock and changed state before we did.
        if (!cacheValid) {
          data = ...
          cacheValid = true;
        }
        // Downgrade by acquiring read lock before releasing write lock
        rwl.readLock().lock();
        rwl.writeLock().unlock(); // Unlock write, still hold read
     }

     use(data);
     rwl.readLock().unlock();
   }
 }

 學習在繼續!!!Go!Go!Go!!!