java乐观锁原理与实现案例分析
本文实例讲述了java乐观锁原理与实现。分享给大家供大家参考,具体如下:
简单说说乐观锁。乐观锁是相对于悲观锁而言。悲观锁认为,这个线程,发生并发的可能性极大,线程冲突几率大,比较悲观。一般用synchronized实现,保证每次操作数据不会冲突。乐观锁认为,线程冲突可能性小,比较乐观,直接去操作数据,如果发现数据已经被更改(通过版本号控制),则不更新数据,再次去重复 所需操作,知道没有冲突(使用递归算法)。
因为乐观锁使用递归+版本号控制 实现,所以,如果线程冲突几率大,使用乐观锁会重复很多次操作(包括查询数据库),尤其是递归部分逻辑复杂,耗时和耗性能,是低效不合适的,应考虑使用悲观锁。
乐观锁悲观锁的选择:
- 乐观锁:并发冲突几率小,对应模块递归操作简单 时使用
- 悲观锁:并发几率大,对应模块操作复杂 时使用
下面给出一个乐观锁实例:
/**
* 自动派单
* 只查出一条 返回list只是为了和查询接口统一
* 视频审核订单不派送
* @param paramMap
* @return
*/
public List<AutomaticAssignDto> automaticAssign(Map<String, Object> paramMap){
//派送规则
String changeSortSet = RedisCacheUtil.getValue(CACHE_TYPE.APP, "changeSortSet");
if (StringUtils.isBlank(changeSortSet)) {
changeSortSet = customerManager.getDictionaryByCode("changeSortSet");
if (StringUtils.isNotBlank(changeSortSet)) {
RedisCacheUtil.addValue(CACHE_TYPE.APP, "changeSortSet", changeSortSet,30,TimeUnit.DAYS);
} else {
changeSortSet = ConstantsUtil.AssignRule.FIFO; // 默认先进先审
}
}
AutomaticAssignDto automaticAssignDto = new AutomaticAssignDto();
automaticAssignDto.setChangeSortSet(changeSortSet);
automaticAssignDto.setUserTeam(CommonUtils.getValue(paramMap, "userTeam"));
List<AutomaticAssignDto> waitCheckList = automaticAssignMybatisDao.automaticAssignOrder(automaticAssignDto);
if(waitCheckList != null && waitCheckList.size()>0){
automaticAssignDto = waitCheckList.get(0);
automaticAssignDto.setSendStatus(ConstantsUtil.SendStatus.SEND);
automaticAssignDto.setBindTime(new Date());
automaticAssignDto.setUserId(Long.parseLong(paramMap.get("userId").toString()) );
int sum = automaticAssignMybatisDao.bindAutomaticAssignInfo(automaticAssignDto);
if(sum == 1){
return waitCheckList;
}else{
//已被更新 则再次获取
return automaticAssign(paramMap);
}
}else{
return null;
}
}
对应更新的sql:
<update id="bindAutomaticAssignInfo" parameterType="com.star.manager.dto.apply.AutomaticAssignDto">
UPDATE t_automatic_assign
SET
SEND_STATUS = #{sendStatus} ,
BIND_TIME = SYSDATE() ,
LOCKED_FINISHTIME = SYSDATE(),
USER_ID = #{userId} ,
VERSION = VERSION + 1,
UPDATE_DATE = SYSDATE()
WHERE SLT_ACCOUNT_ID = #{sltAccountId}
AND VERSION = #{version}
</update>
简要说明:表设计时,需要往表里加一个version字段。每次查询时,查出带有version的数据记录,更新数据时,判断数据库里对应id的记录的version是否和查出的version相同。若相同,则更新数据并把版本号+1;若不同,则说明,该数据发送并发,被别的线程使用了,进行递归操作,再次执行递归方法,知道成功更新数据为止。
上述automaticAssign方法即实现了一个乐观锁,作用是冲数据库里更新一条数据病返回前端。如果并发率大,一次请求可能则会重复执行很多次automaticAssign,则性能低。如果并发很乐观,用户请求少,则不需要用synchronized,多线程时性能高。
在此只是简单说说,详细概念等需另行查阅相关资料。
更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。
相关文章
Spring StateMachine实现状态机使用示例详解
本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解析状态同步、事件触发与数据持久化机制,感兴趣的朋友跟随小编一起看看吧2025-07-07
EasyExcel与Apache POI版本冲突导致`NoSuchMethodError`异常的解决方法
本文介绍了EasyExcel与ApachePOI版本冲突导致`NoSuchMethodError`异常的原因,并提供了两种解决方案:排除EasyExcel自带的POI并手动指定统一版本,或者移除自己引入的POI,同时,也强调了在使用EasyExcel时避免单独引入POI的重要性,需要的朋友可以参考下2025-11-11
SpringBoot基于Sentinel在服务上实现接口限流
这篇文章主要介绍了SpringBoot基于Sentinel在服务上实现接口限流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2020-10-10
AbstractProcessor扩展MapStruct自动生成实体映射工具类
这篇文章主要为大家介绍了AbstractProcessor扩展MapStruct自动生成实体映射工具类实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-01-01


最新评论