ReadWriteLock用法

對象的方法中一旦加入synchronized修飾,則任何時刻只能有一個線程訪問synchronized修飾的方法。假設有個數據對象擁有寫方法與讀方法,多線程環境中要想保證數據的安全,需對該對象的讀寫方法都要加入 synchronized同步塊。這樣任何線程在寫入時,其它線程無法讀取與改變數據;如果有線程在讀取時,其他線程也無法讀取或寫入。這種方式在寫入操作遠大於讀操作時,問題不大,而當讀取遠遠大於寫入時,會造成性能瓶頸,因爲此種情況下讀取操作是可以同時進行的,而加鎖操作限制了數據的併發讀取。            ReadWriteLock解決了這個問題,當寫操作時,其他線程無法讀取或寫入數據,而當讀操作時,其它線程無法寫入數據,但卻可以讀取數據 。


且看 以下例子

  1. public class ReadWriteLockDemo {  

  2.     static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  

  3.   

  4.     public static void main(String[] args) {  

  5.         Data data = new Data();  

  6.         Worker t1 = new Worker(data,true);  

  7.         Worker t2 = new Worker(data,true);  

  8.         t1.start();  

  9.         t2.start();  

  10.     }  

  11.   

  12.     static class Worker extends Thread {  

  13.         Data data;  

  14.         boolean read;  

  15.   

  16.         public Worker(Data data, boolean read) {  

  17.             this.data = data;  

  18.             this.read = read;  

  19.         }  

  20.   

  21.         public void run() {  

  22.             if (read)  

  23.                 data.get();  

  24.             else  

  25.                 data.set();  

  26.         }  

  27.     }  

  28.   

  29.     static class Data {  

  30.         ReadWriteLock lock = new ReentrantReadWriteLock();  

  31.         Lock read = lock.readLock();  

  32.         Lock write = lock.writeLock();  

  33.         public  void set() {  

  34.             write.lock();  

  35.             System.out.println(Thread.currentThread().hashCode()  

  36.                     + " set:begin " + sdf.format(new Date()));  

  37.             try {  

  38.                 Thread.sleep(5000);  

  39.                 //  

  40.             } catch (Exception e) {  

  41.   

  42.             } finally {  

  43.                 System.out.println(Thread.currentThread().hashCode() + " set:end "  

  44.                         + sdf.format(new Date()));  

  45.                 write.unlock();  

  46.             }  

  47.               

  48.   

  49.         }  

  50.   

  51.         public  int get() {  

  52.             read.lock();  

  53.             System.out.println(Thread.currentThread().hashCode()  

  54.                     + " get :begin " + sdf.format(new Date()));  

  55.             try {  

  56.                 Thread.sleep(5000);  

  57.                 //  

  58.             } catch (Exception e) {  

  59.   

  60.             } finally {  

  61.                 System.out.println(Thread.currentThread().hashCode() + " get :end "  

  62.                         + sdf.format(new Date()));  

  63.                 read.unlock();  

  64.             }  

  65.               

  66.   

  67.             return 1;  

  68.         }  

  69.     }  


兩個線程均是讀線程,結果如下

 22474382 get :begin 2011-04-16 18:26:13
4699264 get :begin 2011-04-16 18:26:13
22474382 get :end 2011-04-16 18:26:18
4699264 get :end 2011-04-16 18:26:18

 

兩讀線程均可同時讀取數據,下面看一個是讀線程,一個寫線程的情況

Data data = new Data();
  Worker t1 = new Worker(data,false);
  Worker t2 = new Worker(data,true);
  
  t2.start();
  Thread.sleep(100);
  t1.start();

 

先啓動讀取線程,再啓動寫入線程,看結果 

14718739 get :begin 2011-04-16 18:54:46
14718739 get :end 2011-04-16 18:54:51
14737862 set:begin 2011-04-16 18:54:51
14737862 set:end 2011-04-16 18:54:56

可以看到讀取線程工作時,寫入線程是不能訪問數據的


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章