1.实现一个读写缓存的操作,假设开始没有加锁的时候,会出现什么情况
import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; class MyCache { private volatile Map<String, Object> map = new HashMap<>(); public void put(String key, Object value) { System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key); try { // 模拟网络拥堵,延迟0.3秒 TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } map.put(key, value); System.out.println(Thread.currentThread().getName() + "\t 写入完成"); } public void get(String key) { System.out.println(Thread.currentThread().getName() + "\t 正在读取:"); try { // 模拟网络拥堵,延迟0.3秒 TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } Object value = map.get(key); System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + value); } } public class ReadWriteWithoutLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); // 线程操作资源类,5个线程写 for (int i = 0; i < 5; i++) { final int tempInt = i; new Thread(() -> { myCache.put(tempInt + "", tempInt + ""); }, String.valueOf(i)).start(); } // 线程操作资源类, 5个线程读 for (int i = 0; i < 5; i++) { final int tempInt = i; new Thread(() -> { myCache.get(tempInt + ""); }, String.valueOf(i)).start(); } } }
2.执行结果
0 正在写入:0 1 正在写入:1 3 正在写入:3 2 正在写入:2 4 正在写入:4 0 正在读取: 1 正在读取: 2 正在读取: 4 正在读取: 3 正在读取: 1 写入完成 4 写入完成 0 写入完成 2 写入完成 3 写入完成 3 读取完成:3 0 读取完成:0 2 读取完成:2 1 读取完成:null 4 读取完成:null
3.看到有些线程读取到null,可用ReentrantReadWriteLock解决
package com.mydemo; import java.util.HashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteWithoutLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 0; i < 5; i++) { final int i1=i; new Thread(()->{ myCache.put(i1+"",i1+""); },String.valueOf(i)).start(); } for (int i = 0; i < 5; i++) { final int i1=i; new Thread(()->{ myCache.get(i1+""); },String.valueOf(i)).start(); } } } class MyCache{ private volatile HashMap<String,String> map=new HashMap<>(); ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock(); public void put(String key,String value){ readWriteLock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"\t 正在写入"+key); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } map.put(key,value); System.out.println(Thread.currentThread().getName()+"\t 写入完毕"+key); readWriteLock.writeLock().unlock(); } public void get(String key){ readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"\t正在读取:"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } String s = map.get(key); System.out.println(Thread.currentThread().getName()+"\t读取完"+s); readWriteLock.readLock().unlock(); } }
4.执行结果
1 正在写入1 1 写入完毕1 0 正在写入0 0 写入完毕0 2 正在写入2 2 写入完毕2 3 正在写入3 3 写入完毕3 4 正在写入4 4 写入完毕4 0 正在读取: 1 正在读取: 2 正在读取: 3 正在读取: 4 正在读取: 4 读取完4 3 读取完3 2 读取完2 1 读取完1 0 读取完0
对ReentrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?