乐观锁与悲观锁以及使用场景

乐观锁

  • 含义:

每次使用数据时,都不会认为数据会有变动,主要突出一个开心,所以不上锁,在提交数据的时候进行验证,判断数据是否真的被别人修改过。

  • 场景:

适用于读多写少的场景,这样可以提高吞吐量。

  • 实现:
  • 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等

你可能感兴趣的:(乐观锁与悲观锁以及使用场景)