多线程之ReadWriteLock模拟缓存(九)
错误案例1:
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; } } }