其他分享
首页 > 其他分享> > Spring事务传播行为二

Spring事务传播行为二

作者:互联网

接着上一篇章继续说

这个需要结合着具体的案例来进行分析。

结合着我之前写的一篇文章:事务失效

看下代码:

@Transactional
public void sellProduct() throws ClassNotFoundException {
    log.info("----------------->>>>>>>开启日志<<<<<------------------------");
    LOCK.lock();
    try {
        System.out.println(Thread.currentThread().getName() + ":抢到锁了,进入到方法中来");
        // 首先查询库存
        Product product = productMapper.selectById(1L);
        Integer productcount = product.getProductcount();
        System.out.println(Thread.currentThread().getName() + ":当前库存是:" + productcount);
        if (productcount > 0) {
            product.setProductcount(productcount - 1);
            // 更新操作
            productMapper.updateById(product);
            Buy buy = new Buy();
            buy.setProductname(product.getProductname());
            buy.setUsername(Thread.currentThread().getName());
            // 保存操作
            buyMapper.insert(buy);
            System.out.println(Thread.currentThread().getName() + ":减库存,创建订单完毕!");
        } else {
            System.out.println(Thread.currentThread().getName() + ":没有库存了");
        }
    } finally {
        System.out.println(Thread.currentThread().getName() + ":释放锁");
        // 释放锁
        LOCK.unlock();
    }
}

首先分析,多个线程进来的时候,都将开启一个新的数据库连接。但是因为使用了LOCK锁,那么这里达到的效果就是多个线程拥有的自己的数据库连接,但是在当前来说,只有一个线程在操作数据库连接。

这是一种明显的使用错误情况。因为只要一个线程在执行,而其他持有数据库连接的线程就只能够等待。数据库连接是非常宝贵的资源了。但是在这里的代码中,却是没有使用。但是却一直持有,效率很低。所以针对这种情况,需要来进行处理。

最主要的原因在于:锁都已经释放了,但是数据库连接还没有提交事务

这种情况,代价最低的解决方式,我觉得类似如下结构:

public void sellProduct() throws ClassNotFoundException {
    log.info("----------------->>>>>>>开启日志<<<<<------------------------");
    LOCK.lock();
    try {
		AopContext.getCurrentAOP().sellProductZ();
    } finally {
        System.out.println(Thread.currentThread().getName() + ":释放锁");
        // 释放锁
        LOCK.unlock();
    }
}

需要开启一下,将当前对象保存到当前环境中来。

@Transactional
public void sellProductZ() {
    System.out.println(Thread.currentThread().getName() + ":抢到锁了,进入到方法中来");
    // 首先查询库存
    Product product = productMapper.selectById(1L);
    Integer productcount = product.getProductcount();
    System.out.println(Thread.currentThread().getName() + ":当前库存是:" + productcount);
    if (productcount > 0) {
        product.setProductcount(productcount - 1);
        // 更新操作
        productMapper.updateById(product);
        Buy buy = new Buy();
        buy.setProductname(product.getProductname());
        buy.setUsername(Thread.currentThread().getName());
        // 保存操作
        buyMapper.insert(buy);
        System.out.println(Thread.currentThread().getName() + ":减库存,创建订单完毕!");
    } else {
        System.out.println(Thread.currentThread().getName() + ":没有库存了");
    }
}

但是也可以有另外的方式来进行解决,开两个不同的数据库事务来进行处理。

当前没有遇到过这种情况,如果遇到了,那么可以来继续进行分析。

标签:事务,buy,currentThread,Thread,Spring,getName,product,传播,println
来源: https://www.cnblogs.com/likeguang/p/16686984.html