介紹:
讀寫鎖實際是一種特殊的
自旋鎖,它把對共享資源的訪問者划分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於自旋鎖而言,能提高並發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實際的邏輯CPU數。
寫者是排他性的,一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數相關),但不能同時既有讀者又有寫者。
在讀寫鎖保持期間也是搶占失效的。
如果讀寫鎖當前沒有讀者,也沒有寫者,那么寫者可以立刻獲得讀寫鎖,否則它必須自旋在那里,直到沒有任何寫者或讀者。
如果讀寫鎖沒有寫者,那么讀者可以立即獲得該讀寫鎖,否則讀者必須自旋在那里,直到寫者釋放該讀寫鎖。
並發線程下,所有線程都執行讀的操作 不會有問題
並發線程下,部分讀部分寫會不會有問題 會發生寫沖突
並發線程下,所有線程都執行寫會不會有問題 會發生寫沖突
示例:
public class ReadWriteLock { //創建一個集合 static Map<String,String> map=new HashMap<String,String>(); //創建一個讀寫鎖 static ReentrantReadWriteLock lock=new ReentrantReadWriteLock(); //獲取讀鎖 static Lock readLock=lock.readLock(); //獲取寫鎖 static Lock writeLock=lock.writeLock(); //寫操作 public Object put(String key,String value){ writeLock.lock(); try { System.out.println("Write正在執行寫操作~"); Thread.sleep(100); String put = map.put(key, value); System.out.println("Write寫操作執行完畢~"); return put; } catch (InterruptedException e) { e.printStackTrace(); }finally { writeLock.unlock(); } return null; } //寫操作 public Object get(String key){ readLock.lock(); try { System.out.println("Read正在執行讀操作~"); Thread.sleep(100); String value = map.get(key); System.out.println("Read讀操作執行完畢~"); return value; } catch (InterruptedException e) { e.printStackTrace(); }finally { readLock.unlock(); } return null; } public static void main(String[] args) { ReadWriteLock lock=new ReadWriteLock(); for (int i = 0; i < 10; i++) { int finalI = i; new Thread(()->{ try { //寫操作 lock.put(finalI +"","value"+finalI); //讀操作 System.out.println(lock.get(finalI+"")); } catch (Exception e) { e.printStackTrace(); } }).start(); } } }
總結:
讀鎖是共享的
寫鎖是排他的
互斥原則:
- 讀-讀能共存,
- 讀-寫不能共存,
- 寫-寫不能共存。