你的位置:首页 > Java教程

[Java教程]读写锁ReadWriteLock和缓存实例


读写锁:多个读锁不互斥,读锁与些锁互斥,写锁与写锁互斥。即:读的时候不允许写,写的时候不允许读,可以同时读。
     synchronized关键字和普通的Lock构造的锁,会造成读与读之间的互斥,因此读写锁可提高性能。
 
例子1:三个线程同时对一个共享数据进行读写。
 
import java.util.Random;
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; // 共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
       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();
                            // 获取写锁开始写数据
                            rwl.writeLock().lock();
                            try {
                                   // 再次判断该值是否为空,因为如果两个写线程都阻塞在这里,
                                   // 当一个线程被唤醒后value的值为null则进行数据加载,当另外一个线程也被唤醒如果不判断就会执行两次写  
                                   if (value == null) {
                                         value = "" ; // query 数据库
                                          cache.put(key, value);
                                  }
                           } finally {
                                   rwl.writeLock().unlock(); // 释放写锁
                           }
                            rwl.readLock().lock(); // 写完之后降级为读锁
                     }
              } finally {
                      rwl.readLock().unlock(); // 释放读锁
              }
 
               return value;
       }
 

}