读写锁ReadWriteLock和缓存实例

读写锁:多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。即:读的时候不允许写,写的时候不允许读,可以同时读。
     synchronized关键字和普通的Lock构造的锁,会造成读与读之间的互斥,因此读写锁可提高性能。
 
例子1:三个线程同时对一个共享数据进行读写。
 
 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 }

 

例子2:缓存实例
 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 }

 

posted @ 2015-12-11 21:15  吞噬天帝  阅读(979)  评论(0编辑  收藏  举报