Java之乐观锁与悲观锁

一、问题描述
最近在项目开发中遇到一个场景,一个共享资源可能在同一时间被多个线程访问并更新,此时一般有两种解决方案。第一种就是在相应的方法上加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则不执行更新操作,并提示用户异常,重新尝试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员阿坤...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值