• 读写锁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 }
    复制代码
  • 相关阅读:
    前端Ajax/JS/HTML+后端SpringMVC(二)
    前端Ajax/JS/HTML+后端SpringMVC(一)
    Redis 简介及应用
    项目中使用 MyBatis(二)
    L2d插件
    [转载] 栈内存和堆内存
    Hbase排错
    matplotlib中文乱码
    cocos2dx 一些好网站
    esclipe中接入SDK时引用另一个工程或Jar
  • 原文地址:https://www.cnblogs.com/zhangyuhang3/p/6872664.html
Copyright © 2020-2023  润新知