首页 > 编程语言 >Java:锁方案

Java:锁方案

时间:2022-10-31 10:12:45浏览次数:45  
标签:方案 加锁 Java lock stockMapper 共享资源 JVM stock

加锁的前提

共享资源被多个线程同时所消费,造成业务逻辑错误

加锁位置

共享资源在哪,就对哪进行加锁

  1. 如果共享资源在应用上,可以使用JVM自带的本地锁,如synchronized和lock
  2. 如果在数据库上,使用数据库自带的锁

共享资源在应用上

大家常常看到演示的例子,设个静态变量作为应用共享资源,然后使用JVM本地锁来处理,这是没有任何问题的。

共享资源在Mysql上

实际生产中,共享变量极少是在放在应用上,大部分都是放在数据库中进行保存。如果此时再使用JVM本地锁加锁,就会出现并发问题。举例一段代码:

public void updateStock(){
        lock.lock();
        try {
            Stock stock = this.stockMapper.selectone(new QueryWrapper<Stock>().eq("product_code","1001");
            if (stock != null && stock.getCount() > 0){
                stock.setcount(stock.getCount() - 1);
                this.stockMapper.updateById(stock);
            }
        }finally {
            lock.unlock();
        }
    }

上面的业务逻辑是:

  1. 查询库存
  2. 代码层数量减一
  3. 更新库存

由于这段业务代码会出现并发问题,因此我们加了JVM本地锁。但在三种情况下,本地锁并不能保证业务安全。

  1. 锁对象是多例
  2. 事务
  3. 集群部署

锁对象多例

这个很好理解,我们说过加锁有个隐藏的前提,锁是同一把。这种其实还挺好避免,实际开发spring默认是单例,只要我们不去瞎改,一般不会此种情况

事务

有人好奇加了事务,咋就突然有数据安全问题呢。先给大家贴下代码:

    @Transactional
    public void updateStock(){
        lock.lock();
        try {
            Stock stock = this.stockMapper.selectone(new QueryWrapper<Stock>().eq("product_code","1001");
            if (stock != null && stock.getCount() > 0){
                stock.setcount(stock.getCount() - 1);
                this.stockMapper.updateById(stock);
            }
        }finally {
            lock.unlock();
        }

        //执行后续代码
        ....
    }

给大家
image
image

标签:方案,加锁,Java,lock,stockMapper,共享资源,JVM,stock
From: https://www.cnblogs.com/ibcdwx/p/16843324.html

相关文章