读写锁:多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。即:读的时候不允许写,写的时候不允许读,可以同时读。

     synchronized关键字和普通的Lock构造的锁,会造成读与读之间的互斥,因此读写锁可提高性能。

例子1:三个线程同时对一个共享数据进行读写。

读写锁ReadWriteLock和缓存实例_import

 1 import java.util.Random; 2 import java.util.concurrent.locks.ReadWriteLock; 3 import java.util.concurrent.locks.ReentrantReadWriteLock; 4   5 public class ReadWriteLockTest { 6         public static void main(String[] args) { 7                final Queue queue = new Queue(); 8                for (int i = 0; i < 3; i++) { 9                       new Thread() {10                             public void run() {11                                    while (true) {12                                          queue.get();13                                   }14                            }15  16                      }.start();17  18                       new Thread() {19                             public void run() {20                                    while (true) {21                                          queue.put( new Random().nextInt(10000));22                                   }23                            }24  25                      }.start();26               }27  28        }29 }30  31 class Queue {32         private Object data = null; // 共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。33        ReadWriteLock rwl = new ReentrantReadWriteLock();34  35         public void get() {36                rwl.readLock().lock();37                try {38                      System. out.println(Thread.currentThread().getName() + " be ready to read data!");39                      Thread. sleep((long) (Math. random() * 1000));40                      System. out.println(Thread.currentThread().getName() + " have read data :" + data);41               } catch (InterruptedException e) {42                      e.printStackTrace();43               } finally {44                       rwl.readLock().unlock();45               }46        }47  48         public void put(Object data) {49  50                rwl.writeLock().lock();51                try {52                      System. out.println(Thread.currentThread().getName() + " be ready to write data!");53                      Thread. sleep((long) (Math. random() * 1000));54                       this.data = data;55                      System. out.println(Thread.currentThread().getName() + " have write data: " + data);56               } catch (InterruptedException e) {57                      e.printStackTrace();58               } finally {59                       rwl.writeLock().unlock();60               }61  62        }63 }

读写锁ReadWriteLock和缓存实例_import

 

例子2:缓存实例

读写锁ReadWriteLock和缓存实例_import

 1 import java.util.HashMap; 2 import java.util.Map; 3 import java.util.concurrent.locks.ReadWriteLock; 4 import java.util.concurrent.locks.ReentrantReadWriteLock; 5   6 public class CacheDemo { 7   8         private static Map<String, Object> cache = new HashMap<String, Object>(); 9  10         private ReadWriteLock rwl = new ReentrantReadWriteLock();11  12         public Object getData(String key) {13                // 当线程开始读时,首先开始加上读锁14                rwl.readLock().lock();15               Object value = null;16                try {17                      value = cache.get(key);18                       // 判断是否存在值19                       if (value == null) {20                             // 在开始写之前,首先要释放读锁,否则写锁无法拿到21                             rwl.readLock().unlock();22                             // 获取写锁开始写数据23                             rwl.writeLock().lock();24                             try {25                                    // 再次判断该值是否为空,因为如果两个写线程都阻塞在这里,26                                    // 当一个线程被唤醒后value的值为null则进行数据加载,当另外一个线程也被唤醒如果不判断就会执行两次写  27                                    if (value == null) {28                                          value = "" ; // query 数据库29                                           cache.put(key, value);30                                   }31                            } finally {32                                    rwl.writeLock().unlock(); // 释放写锁33                            }34                             rwl.readLock().lock(); // 写完之后降级为读锁35                      }36               } finally {37                       rwl.readLock().unlock(); // 释放读锁38               }39  40                return value;41        }42  43 }

读写锁ReadWriteLock和缓存实例_import