Java之乐观锁与悲观锁

导读:本篇文章讲解 Java之乐观锁与悲观锁,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、问题描述
最近在项目开发中遇到一个场景,一个共享资源可能在同一时间被多个线程访问并更新,此时一般有两种解决方案。第一种就是在相应的方法上加synchronized关键字,我们称之为悲观锁,即锁住共享资源,等待当前线程访问并更新完毕,其他线程才可以操作共享资源。第二种是不给资源加锁,即无锁,线程可以直接去访问并更新资源,只是在更新资源的同时判断该共享资源有没有被更新,如果没有被更新,则执行更新操作,反之,提示异常或者自动重试。
二、举例说明
java锁主要是对比较敏感的数据进行设置,防止出现脏数据的现象,比如我们有一张user表,对应的实体类

import lombok.Data
@Data
@TableName("user")
public class User{
	//主键
	Long id;
	//用户名
	String username;
	用户密码
	String password;
	//用户余额
	Integer balance;
}

有一个方法可以更新用户余额,

@Autowired
private final UserDao userDao;
/**
* @param userId 用户id
* @param consume 用户消费的金额 
*/
public Boolean update(Long userId, Integer consume){
	//通过用户id找到用户
	User user = userService.findById(userId);
	//获得更新后的余额(1)
	int updateBalance = user.getBalance() - consume;
	//保存更新的余额
	user.setBalance(balance);
	//调用userDao更新数据库
	userDao.update(user);
}

一般业务里面我们可以通过这样的方式实现对用户字段进行更新,但是可能同时有其他线程要更新这个字段值,那我们
在进行(1)这一步的时候,拿到了用户的余额,此时资源还没有被更新,当执行到数据库sql语句的时候,update user set balance = #{updateBalance}在此操作进行之前用户余额被其他线程修改,那么我们忽略了这个线程的修改操作(可能是平台给予的奖励等等)。那么怎么解决呢?
可以使用乐观锁的原理,在mapper种的update语句可以调整为

<update id = update>
	update user set user.balance = #{updateBalance}
	<!-- 加上一个where判断 getBalance是方法传进来的用户余额-->
	 where user.balance = #{getBalance}
</update>

这样就可以解决这个问题,如果getBalance != user.balance则不执行更新操作,并提示用户异常,重新尝试

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71724.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!