• Java锁_读写锁


    独占锁:是指锁一次只能被一个线程持有,ReentrantLock和Synchronized都是独占锁。

    共享锁:是指锁可以被多个线程持有。

    对于ReentrantReadWriteLock,其读锁是共享锁,写锁是独占锁。

     

     代码示例:如果不设置锁,下面这块代码执行后就会造成一段写操作在完成之前被多个其他操作打断。

     1 package com.freud.algorithm.other;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 import java.util.concurrent.TimeUnit;
     6 import java.util.concurrent.locks.Lock;
     7 import java.util.concurrent.locks.ReentrantLock;
     8 
     9 /**
    10  * 资源类
    11  */
    12 class MyCache {
    13 
    14     private volatile Map<String, Object> map = new HashMap<>();
    15     // private Lock lock = new ReentrantLock();
    16     public void put(String key, Object value) {
    17 
    18         System.out.println(Thread.currentThread().getName() + "	 正在写入:" + key);
    19         // 暂停一会儿线程
    20         try {
    21             TimeUnit.MILLISECONDS.sleep(300);
    22         } catch (InterruptedException e) {
    23             e.printStackTrace();
    24         }
    25         map.put(key, value);
    26         System.out.println(Thread.currentThread().getName() + "	 写入完成");
    27     }
    28 
    29     public void get(String key) {
    30 
    31         System.out.println(Thread.currentThread().getName() + "	 正在读取:");
    32         // 暂停一会儿线程
    33         try {
    34             TimeUnit.MILLISECONDS.sleep(300);
    35         } catch (InterruptedException e) {
    36             e.printStackTrace();
    37         }
    38         Object value = map.get(key);
    39         System.out.println(Thread.currentThread().getName() + "	 读取完成:" + value);
    40     }
    41 }
    42 
    43 /**
    44  * 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
    45  * 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写
    46  * 小总结:
    47  *      读-读能共存
    48  *      读-写不能共存
    49  *      写-写不能共存
    50  */
    51 public class ReadWriteLockDemo {
    52 
    53     public static void main(String[] args) {
    54 
    55         MyCache myCache = new MyCache();
    56 
    57         for (int i = 0; i < 5; i++) {
    58             final int tempInt = i;
    59             new Thread(() -> {
    60                 myCache.put(tempInt + "", tempInt + "");
    61             }, String.valueOf(i)).start();
    62         }
    63 
    64         for (int i = 0; i < 5; i++) {
    65             final int tempInt = i;
    66             new Thread(() -> {
    67                 myCache.get(tempInt + "");
    68             }, String.valueOf(i)).start();
    69         }
    70     }
    71 }

    打印:

     1 "C:Program FilesJavajdk1.8.0_191injava" "-javaagent:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6libidea_rt.jar=12592:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_191jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_191jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_191jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_191jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_191jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_191jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_191jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_191jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_191jrelibext
    ashorn.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_191jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_191jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_191jrelibjce.jar;C:Program FilesJavajdk1.8.0_191jrelibjfr.jar;C:Program FilesJavajdk1.8.0_191jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_191jrelibjsse.jar;C:Program FilesJavajdk1.8.0_191jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_191jrelibplugin.jar;C:Program FilesJavajdk1.8.0_191jrelib
    esources.jar;C:Program FilesJavajdk1.8.0_191jrelib
    t.jar;E:practisealgorithmoutproductionalgorithm" com.freud.algorithm.other.ReadWriteLockDemo
     2 1     正在写入:1
     3 0     正在写入:0
     4 2     正在写入:2
     5 3     正在写入:3
     6 4     正在写入:4
     7 0     正在读取:
     8 1     正在读取:
     9 2     正在读取:
    10 3     正在读取:
    11 4     正在读取:
    12 1     写入完成
    13 1     读取完成:1
    14 0     读取完成:0
    15 0     写入完成
    16 2     写入完成
    17 4     写入完成
    18 3     写入完成
    19 4     读取完成:null
    20 3     读取完成:null
    21 2     读取完成:2
    22 
    23 Process finished with exit code 0

    为了解决这个问题,使得写操作保证原子性不被其他线程打断,加了ReadWriteLock。

      1 package com.freud.algorithm.other;
      2 
      3 import java.util.HashMap;
      4 import java.util.Map;
      5 import java.util.concurrent.TimeUnit;
      6 import java.util.concurrent.locks.Lock;
      7 import java.util.concurrent.locks.ReentrantLock;
      8 import java.util.concurrent.locks.ReentrantReadWriteLock;
      9 
     10 /**
     11  * 资源类
     12  */
     13 class MyCache {
     14 
     15     private volatile Map<String, Object> map = new HashMap<>();
     16     // 传统的Lock不足以满足需求
     17     // private Lock lock = new ReentrantLock();
     18     /**
     19      * JUC提供了ReentrantReadWriteLock
     20      */
     21     private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
     22 
     23     /**
     24      * put方法
     25      * @param key
     26      * @param value
     27      */
     28     public void put(String key, Object value) {
     29 
     30         rwLock.writeLock().lock();
     31         try {
     32             System.out.println(Thread.currentThread().getName() + "	 正在写入:" + key);
     33             // 暂停一会儿线程
     34             try {
     35                 TimeUnit.MILLISECONDS.sleep(300);
     36             } catch (InterruptedException e) {
     37                 e.printStackTrace();
     38             }
     39             map.put(key, value);
     40             System.out.println(Thread.currentThread().getName() + "	 写入完成");
     41         } catch (Exception e) {
     42             e.printStackTrace();
     43         } finally {
     44             rwLock.writeLock().unlock();
     45         }
     46     }
     47 
     48     /**
     49      * get方法
     50      * @param key
     51      */
     52     public void get(String key) {
     53 
     54         rwLock.readLock().lock();
     55         try {
     56             System.out.println(Thread.currentThread().getName() + "	 正在读取:");
     57             // 暂停一会儿线程
     58             try {
     59                 TimeUnit.MILLISECONDS.sleep(300);
     60             } catch (InterruptedException e) {
     61                 e.printStackTrace();
     62             }
     63             Object value = map.get(key);
     64             System.out.println(Thread.currentThread().getName() + "	 读取完成:" + value);
     65         } catch (Exception e) {
     66             e.printStackTrace();
     67         } finally {
     68             rwLock.readLock().unlock();
     69         }
     70     }
     71 }
     72 
     73 /**
     74  * 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
     75  * 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写
     76  * 小总结:
     77  *      读-读能共存
     78  *      读-写不能共存
     79  *      写-写不能共存
     80  */
     81 public class ReadWriteLockDemo {
     82 
     83     public static void main(String[] args) {
     84 
     85         MyCache myCache = new MyCache();
     86 
     87         for (int i = 0; i < 5; i++) {
     88             final int tempInt = i;
     89             new Thread(() -> {
     90                 myCache.put(tempInt + "", tempInt + "");
     91             }, String.valueOf(i)).start();
     92         }
     93 
     94         for (int i = 0; i < 5; i++) {
     95             final int tempInt = i;
     96             new Thread(() -> {
     97                 myCache.get(tempInt + "");
     98             }, String.valueOf(i)).start();
     99         }
    100     }
    101 }

    打印:

    "C:Program FilesJavajdk1.8.0_191injava" "-javaagent:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6libidea_rt.jar=18187:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_191jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_191jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_191jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_191jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_191jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_191jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_191jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_191jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_191jrelibext
    ashorn.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_191jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_191jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_191jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_191jrelibjce.jar;C:Program FilesJavajdk1.8.0_191jrelibjfr.jar;C:Program FilesJavajdk1.8.0_191jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_191jrelibjsse.jar;C:Program FilesJavajdk1.8.0_191jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_191jrelibplugin.jar;C:Program FilesJavajdk1.8.0_191jrelib
    esources.jar;C:Program FilesJavajdk1.8.0_191jrelib
    t.jar;E:practisealgorithmoutproductionalgorithm" com.freud.algorithm.other.ReadWriteLockDemo
    0     正在写入:0
    0     写入完成
    1     正在写入:1
    1     写入完成
    2     正在写入:2
    2     写入完成
    3     正在写入:3
    3     写入完成
    4     正在写入:4
    4     写入完成
    1     正在读取:
    0     正在读取:
    3     正在读取:
    4     正在读取:
    2     正在读取:
    2     读取完成:2
    4     读取完成:4
    3     读取完成:3
    0     读取完成:0
    1     读取完成:1
    
    Process finished with exit code 0
  • 相关阅读:
    数据结构 -- 栈(一)
    数据结构 -- 栈(二)
    Linux 静态库 & 动态库
    Python及Pycharm安装详细教程
    Makefile研究(三) —— 实际应用
    Makefile研究(二)—— 完整可移植性模板
    Makefile研究 (一)—— 必备语法
    JSON 下 -- jansson 示例
    C语言中的static 详细分析
    Linux 命令 -- tar
  • 原文地址:https://www.cnblogs.com/freud-shen/p/13402630.html
Copyright © 2020-2023  润新知