JUC-ReenactmentReadWriteLock使用
计划一个缓存类
可以向其中put数据(写操作)
也可以向其中get数据(读操作)
public class ReentrantReadWriteLockTest { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 1; i <= 10; i++) { final int temp = i; new Thread(()-> { myCache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); } for (int i = 1; i <= 10; i++) { final int temp = i; new Thread(()-> { myCache.get(temp + ""); }, String.valueOf(i)).start(); } } } class MyCache { private volatile Map<String, String> map = new HashMap<>(); public void put(String key, String value) { System.out.println(Thread.currentThread().getName() + "写入" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "写入ok"); } public String get(String key) { System.out.println(Thread.currentThread().getName() + "读取" + key); String s = map.get(key); System.out.println(Thread.currentThread().getName() + "读取ok"); return s; } } /** * 2写入2 * 5写入5 * 5写入ok * 7写入7 * 7写入ok * 2写入ok * 4写入4 * 4写入ok * 1写入1 * 1写入ok * 6写入6 * 6写入ok * 3写入3 * 3写入ok * 9写入9 * 10写入10 * 10写入ok * 8写入8 * 8写入ok * 9写入ok * 1读取1 * 1读取ok * 2读取2 * 2读取ok * 3读取3 * 3读取ok * 4读取4 * 6读取6 * 6读取ok * 5读取5 * 5读取ok * 7读取7 * 7读取ok * 9读取9 * 10读取10 * 10读取ok * 4读取ok * 9读取ok * 8读取8 * 8读取ok */
不做锁处理,结果输出有误2线程还没写完,5线程就进来写了
使用ReentrantReadWriteLock,完成细粒度锁控制
读-读,可共存
写-读,不可共存
写-写,不可共存
public class ReentrantReadWriteLockTest { public static void main(String[] args) { MyCacheLock myCache = new MyCacheLock(); for (int i = 1; i <= 10; i++) { final int temp = i; new Thread(()-> { myCache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); } for (int i = 1; i <= 10; i++) { final int temp = i; new Thread(()-> { myCache.get(temp + ""); }, String.valueOf(i)).start(); } } } class MyCache { private volatile Map<String, String> map = new HashMap<>(); public void put(String key, String value) { System.out.println(Thread.currentThread().getName() + "写入" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "写入ok"); } public String get(String key) { System.out.println(Thread.currentThread().getName() + "读取" + key); String s = map.get(key); System.out.println(Thread.currentThread().getName() + "读取ok"); return s; } } class MyCacheLock { private volatile Map<String, String> map = new HashMap<>(); private ReadWriteLock readWriteLock = new java.util.concurrent.locks.ReentrantReadWriteLock(); public void put(String key, String value) { // 写入操作使用写锁,上锁 readWriteLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + "写入" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "写入ok"); } catch (Exception e) { e.printStackTrace(); } finally { // 解锁 readWriteLock.writeLock().unlock(); } } public String get(String key) { // 读取操作使用读锁,加锁 readWriteLock.readLock().lock(); String s = null; try { System.out.println(Thread.currentThread().getName() + "读取" + key); s = map.get(key); System.out.println(Thread.currentThread().getName() + "读取ok"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.readLock().unlock(); } return s; } } /** * 1写入1 * 1写入ok * 6写入6 * 6写入ok * 2写入2 * 2写入ok * 7写入7 * 7写入ok * 3写入3 * 3写入ok * 4写入4 * 4写入ok * 5写入5 * 5写入ok * 8写入8 * 8写入ok * 10写入10 * 10写入ok * 9写入9 * 9写入ok * 6读取6 * 8读取8 * 8读取ok * 5读取5 * 5读取ok * 2读取2 * 2读取ok * 4读取4 * 4读取ok * 1读取1 * 1读取ok * 7读取7 * 7读取ok * 3读取3 * 3读取ok * 10读取10 * 10读取ok * 9读取9 * 6读取ok * 9读取ok */
可以发现,写必须等待上一个线程写完之后才可以进行写操作,读可以不用等待读操作,但还是需要等待写操作线程释放锁。
#JUC#