讀寫鎖ReadWriteLock和緩衝執行個體,readwritelock執行個體
讀寫鎖:多個讀鎖不互斥,讀鎖與些鎖互斥,寫鎖與寫鎖互斥。即:讀的時候不允許寫,寫的時候不允許讀,可以同時讀。 synchronized關鍵字和普通的Lock構造的鎖,會造成讀與讀之間的互斥,因此讀寫鎖可提高效能。 例子1:三個線程同時對一個共用資料進行讀寫。 import java.util.Random;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockTest { public static void main(String[] args) { final Queue queue = new Queue(); for (int i = 0; i < 3; i++) { new Thread() { public void run() { while (true) { queue.get(); } } }.start(); new Thread() { public void run() { while (true) { queue.put( new Random().nextInt(10000)); } } }.start(); } }} class Queue { private Object data = null; // 共用資料,只能有一個線程能寫該資料,但可以有多個線程同時讀該資料。 ReadWriteLock rwl = new ReentrantReadWriteLock(); public void get() { rwl.readLock().lock(); try { System. out.println(Thread.currentThread().getName() + " be ready to read data!"); Thread. sleep((long) (Math. random() * 1000)); System. out.println(Thread.currentThread().getName() + " have read data :" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwl.readLock().unlock(); } } public void put(Object data) { rwl.writeLock().lock(); try { System. out.println(Thread.currentThread().getName() + " be ready to write data!"); Thread. sleep((long) (Math. random() * 1000)); this.data = data; System. out.println(Thread.currentThread().getName() + " have write data: " + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwl.writeLock().unlock(); } }} 例子2:緩衝執行個體 import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock; public class CacheDemo { private static Map<String, Object> cache = new HashMap<String, Object>(); private ReadWriteLock rwl = new ReentrantReadWriteLock(); public Object getData(String key) { // 當線程開始讀時,首先開始加上讀鎖 rwl.readLock().lock(); Object value = null; try { value = cache.get(key); // 判斷是否存在值 if (value == null) { // 在開始寫之前,首先要釋放讀鎖,否則寫鎖無法拿到 rwl.readLock().unlock(); // 擷取寫鎖開始寫資料 rwl.writeLock().lock(); try { // 再次判斷該值是否為空白,因為如果兩個寫線程都阻塞在這裡, // 當一個線程被喚醒後value的值為null則進行資料載入,當另外一個線程也被喚醒如果不判斷就會執行兩次寫 if (value == null) { value = "" ; // query 資料庫 cache.put(key, value); } } finally { rwl.writeLock().unlock(); // 釋放寫鎖 } rwl.readLock().lock(); // 寫完之後降級為讀鎖 } } finally { rwl.readLock().unlock(); // 釋放讀鎖 } return value; } }