java读写锁
工作遇到了金钱计算,需要用到读写锁保证数据安全。记录一下。
单纯读没有限制,读写、写写的时候会有安全问题。
hashMap存在并发线程安全问题,而hashtable线程安全但每次修改的时候使用synchronized锁住整个表效率很低。推荐使用ConcurrentHashMap。但ConcurrentHashMap只是保证了put()、get()操作是线程安全。连续的俩个或多个原子操作逻辑后并不一定线程安全,并发问题依然存在。使用putIfAbsent()方法可以同时达到put,get效果,保证了一次读写的数据同步。putIfAbsent(key,value)存数据的时候会根据key去容器中查询,查询到就返回原容器中key对应的value值,并没有更新value值。查询不到的时候就将key,value存入然后返回null。ConcurrentHashMap使用分段锁提高性能。
static ConcurrentHashMap <String, ReentrantReadWriteLock> paycertifyMap=new ConcurrentHashMap<>();
使用map存储流水号和读写锁对象,需要使用的时候 根据从map查询出锁对象然后 tryLock() 只会尝试一次获取锁对象,成功获取返回true。而 lock() 获取不到锁时休眠等待获取为止。然后常规使用 即可。
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//先去map查询是否存在该流水号的写锁对象
if (paycertifyMap.putIfAbsent(bizMnPaycertifyVO.getHkls(), lock) != null) {
//map已存在数据,赋值
lock = paycertifyMap.putIfAbsent(bizMnPaycertifyVO.getHkls(), lock);
}
//等于null 添加成功 锁对象为新增的lock
if (!lock.writeLock().tryLock()) {
//获取锁失败
return -1;
}
//获取锁成功
try {
//测试并发
Thread.sleep(5000);
//逻辑方法
paycertifyAddUpdate(bizMnPaycertifyVO);
} catch (Exception e) {
logger.error("新增/修改支付凭证异常" + e);
} finally {
//释放锁
//一般释放锁需要判断是否由该线程获取的锁,避免释放其他线程锁,但是这里使用了ConcurrentHashMap保证了同一时间只存在一个线程持有该锁
lock.writeLock().unlock();
}
return 0;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)