讀寫鎖:多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥。即:讀的時候不允許寫,寫的時候不允許讀,可以同時讀。
     synchronized關鍵字和普通的Lock構造的鎖,會造成讀與讀之間的互斥,因此讀寫鎖可提高性能。
 
例子1:三個線程同時對一個共享數(shù)據(jù)進行讀寫。
 
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
 
public class ReadWriteLockTest {
        public static void main(String[] args) {
               final Queue queue = new Queue();
               for (int i = 0; i < 3; i++) {
                      new Thread() {
                            public void run() {
                                   while (true) {
                                         queue.get();
                                  }
                           }
 
                     }.start();
 
                      new Thread() {
                            public void run() {
                                   while (true) {
                                         queue.put( new Random().nextInt(10000));
                                  }
                           }
 
                     }.start();
              }
 
       }
}
 
class Queue {
        PRivate Object data = null; // 共享數(shù)據(jù),只能有一個線程能寫該數(shù)據(jù),但可以有多個線程同時讀該數(shù)據(jù)。        ReadWriteLock rwl = new ReentrantReadWriteLock();
 
        public void get() {
               rwl.readLock().lock();
               try {
                     System. out.println(Thread.currentThread().getName() + " be ready to read data!");
                     Thread. sleep((long) (Math. random() * 1000));
                     System. out.println(Thread.currentThread().getName() + " have read data :" + data);
              } catch (InterruptedException e) {
                     e.printStackTrace();
              } finally {
                      rwl.readLock().unlock();
              }
       }
 
        public void put(Object data) {
 
               rwl.writeLock().lock();
               try {
                     System. out.println(Thread.currentThread().getName() + " be ready to write data!");
                     Thread. sleep((long) (Math. random() * 1000));
                      this.data = data;
                     System. out.println(Thread.currentThread().getName() + " have write data: " + data);
              } catch (InterruptedException e) {
                     e.printStackTrace();
              } finally {
                      rwl.writeLock().unlock();
              }
 
       }
}
 
 
例子2:緩存實例
 
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
 
public class CacheDemo {
 
        private static Map<String, Object> cache = new HashMap<String, Object>();
 
        private ReadWriteLock rwl = new ReentrantReadWriteLock();
 
        public Object getData(String key) {
               // 當線程開始讀時,首先開始加上讀鎖
               rwl.readLock().lock();
              Object value = null;
               try {
                     value = cache.get(key);
                      // 判斷是否存在值
                      if (value == null) {
                            // 在開始寫之前,首先要釋放讀鎖,否則寫鎖無法拿到
                            rwl.readLock().unlock();
                            // 獲取寫鎖開始寫數(shù)據(jù)
                            rwl.writeLock().lock();
                            try {
                                   // 再次判斷該值是否為空,因為如果兩個寫線程都阻塞在這里,
                                   // 當一個線程被喚醒后value的值為null則進行數(shù)據(jù)加載,當另外一個線程也被喚醒如果不判斷就會執(zhí)行兩次寫  
                                   if (value == null) {
                                          cache.put(key, value);
                                  }
                           } finally {
                                   rwl.writeLock().unlock(); // 釋放寫鎖
                           }
                            rwl.readLock().lock(); // 寫完之后降級為讀鎖
                     }
              } finally {
                      rwl.readLock().unlock(); // 釋放讀鎖
              }
 
               return value;
       }
 
}