乐观锁
- 含义:
每次使用数据时,都不会认为数据会有变动,主要突出一个开心,所以不上锁,在提交数据的时候进行验证,判断数据是否真的被别人修改过。
- 场景:
适用于读多写少的场景,这样可以提高吞吐量。
- 实现:
- 1 数据版本(version),为数据增加一个版本标识,通过对数据库表增加一个字段,读取数据时,也将这个字段读取出来。提交数据时,检测这个字段的值是否发生变化,如果变化,就认为是非法数据,
- 2 时间戳:与第一种方式类似
/**
* 下单减库存
* @param productId
* @return
*/
public boolean updateStock(Long productId){
int updateCnt = 0;
while (updateCnt == 0) {
ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId}", productId);
if (product.getNumber() > 0) {
updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId} AND number=#{number}", productId, product.getNumber());
if(updateCnt > 0){ //更新库存成功
return true;
}
} else { //卖完啦
return false;
}
}
return false;
}
悲观锁
- 含义:
那就是很悲观了,谁都不信,只信自己。所以每次拿数据都会上锁,其他人想改数据,那对不起,得等我改完。
- 场景:
保证数据不会被乱改,屏蔽一切违反数据完整的操作,比如:订单的创建等
- 实现
/**
* 更新库存(使用悲观锁)
* @param productId
* @return
*/
public boolean updateStock(Long productId){
//先锁定商品库存记录
ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId} FOR UPDATE", productId);
if (product.getNumber() > 0) {
int updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId}", productId);
if(updateCnt > 0){ //更新库存成功
return true;
}
}
return false;
其他实现方案:
使用分布式锁。比如redis,Zookeeper等