錯誤案例1:java
package com.net.thread.lock; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author * @Time:2017年8月23日 下午6:09:20 * @version 1.0 * @description 讀寫鎖模擬緩存技術 ,錯誤寫法1 */ public class Example { public static void main(String[] args) { Demo demo = new Demo(); new Thread(new Runnable() { @Override public void run() { System.out.println(demo.get("java")); } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(demo.get("java")); } }).start(); } static class Demo { ReadWriteLock rwl = new ReentrantReadWriteLock(); Map<Object, Object> map = new HashMap<Object, Object>(); boolean flag; public Object get(Object key) { rwl.readLock().lock(); Object value = null; value = map.get(key); //if不安全,若是在這裏邊的value依舊是null,則根本沒有安全保障 if (value == null) { flag = false; rwl.readLock().unlock(); rwl.writeLock().lock(); System.out.println(Thread.currentThread().getName() + " 的flag:" + flag); if (!flag) { value = null; map.put(key, value); flag = true; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } rwl.writeLock().unlock(); rwl.readLock().lock(); } rwl.readLock().unlock(); return value; } } }
錯誤案例2: 在前一個案例中進行改造,但不徹底;此例子中的flag是局部變量,而局部變量其實是線程安全,就至關於每一個線程開始都有一個flag=false的結果,所以,屢次調用,屢次初始化,並無起到緩存的做用緩存
package com.net.thread.lock; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author * @Time:2017年8月23日 下午6:09:20 * @version 1.0 * @description 讀寫鎖模擬緩存技術,錯誤寫法2 */ public class Example2 { public static void main(String[] args) { Demo demo = new Demo(); new Thread(new Runnable() { @Override public void run() { System.out.println(demo.get("java")); } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(demo.get("java")); } }).start(); } static class Demo { ReadWriteLock rwl = new ReentrantReadWriteLock(); Map<Object, Object> map = new HashMap<Object, Object>(); int i = 1; public Object get(Object key) { boolean flag = false; rwl.readLock().lock(); Object value = map.get(key); while (value == null) { System.out.println(Thread.currentThread().getName() + " 的flag:" + flag); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } rwl.readLock().unlock(); rwl.writeLock().lock(); if (!flag) { map.put(key, "初始化"); flag = true; System.out.println(Thread.currentThread().getName() + "寫完後的flag :" + flag + " 次數:" + i); i++; } rwl.writeLock().unlock(); rwl.readLock().lock(); value = map.get(key); } rwl.readLock().unlock(); return value; } } }
正確寫法:安全
package com.net.thread.lock; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author * @Time:2017年8月23日 下午6:09:20 * @version 1.0 * @description 讀寫鎖模擬緩存技術,正確寫法 */ public class Example3 { public static void main(String[] args) { Demo demo = new Demo(); new Thread(new Runnable() { @Override public void run() { System.out.println(demo.get("java")); } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(demo.get("java")); } }).start(); } static class Demo { ReadWriteLock rwl = new ReentrantReadWriteLock(); Map<Object, Object> map = new HashMap<Object, Object>(); int i = 1; boolean flag = false; public Object get(Object key) { rwl.readLock().lock(); Object value = map.get(key); while (value == null) { System.out.println(Thread.currentThread().getName() + " 的flag:" + flag); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } rwl.readLock().unlock(); rwl.writeLock().lock(); if (!flag) { map.put(key, "初始化"); flag = true; System.out.println(Thread.currentThread().getName() + "寫完後的flag :" + flag + " 次數:" + i); i++; } rwl.writeLock().unlock(); rwl.readLock().lock(); value = map.get(key); } rwl.readLock().unlock(); return value; } } }