獨占鎖:是指鎖一次只能被一個執行緒持有,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() + "\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 void get(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 =https://www.cnblogs.com/freud-shen/p/ 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 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 Files\Java\jdk1.8.0_191\bin\java" "-javaagent:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=12592:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\practise\algorithm\out\production\algorithm" 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() + "\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 * @param key 51 */ 52 public void get(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 =https://www.cnblogs.com/freud-shen/p/ 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 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 Files\Java\jdk1.8.0_191\bin\java" "-javaagent:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=18187:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\practise\algorithm\out\production\algorithm" 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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/120990.html
標籤:Java
上一篇:求教:工程檔案夾移動后不能打開了
