独占锁:是指锁一次只能被一个线程持有,ReentrantLock和Synchronized都是独占锁。
共享锁:是指锁可以被多个线程持有。
对于ReentrantReadWriteLock,其读锁是共享锁,写锁是独占锁。
代码示例:如果不设置锁,下面这块代码执行后就会造成一段写操作在完成之前被多个其他操作打断。
1 packagecom.freud.algorithm.other;2
3 importjava.util.HashMap;4 importjava.util.Map;5 importjava.util.concurrent.TimeUnit;6 importjava.util.concurrent.locks.Lock;7 importjava.util.concurrent.locks.ReentrantLock;8
9 /**
10 * 资源类11 */
12 classMyCache {13
14 private volatile Map map = new HashMap<>();15 //private Lock lock = new ReentrantLock();
16 public voidput(String key, Object value) {17
18 System.out.println(Thread.currentThread().getName() + "t 正在写入:" +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() + "t 写入完成");27 }28
29 public voidget(String key) {30
31 System.out.println(Thread.currentThread().getName() + "t 正在读取:");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() + "t 读取完成:" +value);40 }41 }42
43 /**
44 * 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行45 * 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写46 * 小总结:47 * 读-读能共存48 * 读-写不能共存49 * 写-写不能共存50 */
51 public classReadWriteLockDemo {52
53 public static voidmain(String[] args) {54
55 MyCache myCache = newMyCache();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_191binjava" "-javaagent:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6libidea_rt.jar=12592:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6bin" -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_191jrelibextnashorn.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_191jrelibresources.jar;C:Program FilesJavajdk1.8.0_191jrelibrt.jar;E:practisealgorithmoutproductionalgorithm"com.freud.algorithm.other.ReadWriteLockDemo2 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 packagecom.freud.algorithm.other;2
3 importjava.util.HashMap;4 importjava.util.Map;5 importjava.util.concurrent.TimeUnit;6 importjava.util.concurrent.locks.Lock;7 importjava.util.concurrent.locks.ReentrantLock;8 importjava.util.concurrent.locks.ReentrantReadWriteLock;9
10 /**
11 * 资源类12 */
13 classMyCache {14
15 private volatile Map map = new HashMap<>();16 //传统的Lock不足以满足需求17 //private Lock lock = new ReentrantLock();
18 /**
19 * JUC提供了ReentrantReadWriteLock20 */
21 private ReentrantReadWriteLock rwLock = newReentrantReadWriteLock();22
23 /**
24 * put方法25 *@paramkey26 *@paramvalue27 */
28 public voidput(String key, Object value) {29
30 rwLock.writeLock().lock();31 try{32 System.out.println(Thread.currentThread().getName() + "t 正在写入:" +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() + "t 写入完成");41 } catch(Exception e) {42 e.printStackTrace();43 } finally{44 rwLock.writeLock().unlock();45 }46 }47
48 /**
49 * get方法50 *@paramkey51 */
52 public voidget(String key) {53
54 rwLock.readLock().lock();55 try{56 System.out.println(Thread.currentThread().getName() + "t 正在读取:");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() + "t 读取完成:" +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 classReadWriteLockDemo {82
83 public static voidmain(String[] args) {84
85 MyCache myCache = newMyCache();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_191binjava" "-javaagent:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6libidea_rt.jar=18187:E:JetbrainsIntellijIDEAIntelliJ IDEA 2017.2.6bin" -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_191jrelibextnashorn.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_191jrelibresources.jar;C:Program FilesJavajdk1.8.0_191jrelibrt.jar;E:practisealgorithmoutproductionalgorithm"com.freud.algorithm.other.ReadWriteLockDemo0 正在写入: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 读取完成:1Process finished with exit code0