Site Overlay

乐观锁&悲观锁

需要使用锁的场景

满足多个线程共同操作同一共享文件的时候可能发生线程安全问题

悲观锁 (Pessimistic Lock)

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。

Java synchronized 就属于悲观锁的一种实现,每次线程要修改数据时都先获得锁,保证同一时刻只有一个线程能操作数据,其他线程则会被block。

排它锁/读锁:FOR UPDATE

只允许一个线程进行操作,多个线程同时操作时阻塞

共享锁/写锁:LOCK IN SHARE MODE

允许多个线程进行读取操作,但其他操作会阻塞

//悲观锁示例:更新库存
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;
    }

乐观锁 (Optimistic Lock)

顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于读多写少的应用场景,这样可以提高吞吐量。

//乐观锁示例:更新库存
 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;
    }

发表回复

您的电子邮箱地址不会被公开。

A beliving heart is your magic My heart
欢迎来到Diuut的个人博客,这里是我的一些零零碎碎的知识汇总,希望有能帮到你的内容。 | 蜀ICP备2021011635号-1 | Copyright © 2024 Diuut. All Rights Reserved.