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