共享锁:是指锁可以被多个线程持有。
对于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