乐观锁和悲观锁的实现要如何配置?具体概念是什么?

TheDisguiser 2020-05-22 16:46:37 java常见问答 10197

Java开发方向的小伙伴们对乐观锁悲观锁都不会陌生吧,那大家知道乐观锁和悲观锁该如何配置吗?它们的具体概念又是什么呢?快跟我一起来看看吧。

一、乐观锁具体概念及实现

乐观锁,听名字就知道它挺乐观的,在乐观锁下它会假设数据一般情况下不会造成冲突,所以实际上只有在数据已经开始提交更新时,乐观锁才会正式开始对数据的冲突进行检测,如果发现冲突,就会返回给用户错误的信息,让用户自己决定如何去做。

乐观锁这个家伙由于它的乐观,所以它的加锁机制相比于其他锁也是更加宽松的,乐观锁是相对于悲观锁而言的,这是为了避免可能出现的数据库幻读或者业务处理的时间太长等一系列原因引起的数据处理错误的一种机制。

平常而言,乐观锁一般都不太会刻意使用数据库本身的锁机制,它会依赖数据本身来保证数据的正确性。

乐观锁它相信事务之间的数据竞争的概率是比较小的,因此它会尽可能的直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁

乐观锁具体实现:

POJO类

class ProductStock
{
    private Long productId; //商品id
    private Integer number; //库存量
    public Long getProductId()
    {
        return productId;
    }
    public void setProductId(Long productId)
    {
        this.productId = productId;
    }
    public Integer getNumber()
    {
        return number;
    }
    public void setNumber(Integer number)
    {
        this.number = number;
    }
}

实现类

/**
 * 下单减库存
 * @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;
        }

使用乐观锁更新库存的时候不加锁,当提交更新时需要判断数据是否已经被修改(AND number=#{number}),只有在 number等于上一次查询到的number时 才提交更新。

二、悲观锁具体概念及实现

悲观锁,顾名思义,相对于乐观锁而言,它是很悲观的,它认为当你运行一个线程去调用数据的时候,一定会有各种其他乱七八糟的线程来对干扰你。所以,面对这种情况,悲观锁就使线程在取数据时一定都加了一把锁,当别的线程跟你一个时间想要去拿这个数据的话,就会阻塞。

悲观锁具体实现:

POJO类

class ProductStock
{
    private Long productId; //商品id
    private Integer number; //库存量
    public Long getProductId()
    {
        return productId;
    }
    public void setProductId(Long productId)
    {
        this.productId = productId;
    }
    public Integer getNumber()
    {
        return number;
    }
    public void setNumber(Integer number)
    {
        this.number = number;
    }
}

实现类

/**
 * 更新库存(使用悲观锁)
 * @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;
}

以上就是关于乐观锁与悲观锁具体实现的一些内容了,想了解更多与之相关的java常见问答知识,就快来关注我们的网站吧。

推荐阅读:

乐观锁实现方式有几种?乐观锁是什么?

乐观锁是什么?怎么实现乐观锁?

java锁的种类有哪些?类名是什么?