业务逻辑是这样的:在调用服务的时候,先select这一行某个字段有没有值,没有才会去update。但是出现这一个问题,mybatis日志如下:
2022-01-20 13:41:03.523 [http-nio-8081-exec-7] DEBUG [省略]- ==> Preparing: SELECT count(1) FROM A WHERE [省略]
2022-01-20 13:41:03.523 [http-nio-8081-exec-7] DEBUG [省略] - ==> Parameters: 17228600(String)
2022-01-20 13:41:03.536 [http-nio-8081-exec-4] DEBUG [省略]- ==> Preparing: UPDATE A SET [省略]
2022-01-20 13:41:03.526 [http-nio-8081-exec-4] DEBUG [省略]- ==> Parameters: X879(String)
2022-01-20 13:41:05.624 [http-nio-8081-exec-7] DEBUG [省略]- <== Total: 1
2022-01-20 13:41:05.628 [http-nio-8081-exec-4] DEBUG [省略]-<== Updates: 1
线程7去select的时候,会等线程4执行update后,才会返回select结果。最后才是线程4返回update结果。
service层update的方法加了@Transactional,select 没加。
uadate会加锁把
既然是同一个事务的两个操作为什么会出现在两个不同线程中?你写的有问题吧。多线程本来就没有顺序,要保证顺序需要额外代码有很多种实现方式:[1] 使用线程的join方法
[2] 使用主线程的join方法
[3] 使用线程的wait方法
[4] 使用线程的线程池方法
[5] 使用线程的Condition(条件变量)方法
[6] 使用线程的CountDownLatch(倒计数)方法
[7] 使用线程的CyclicBarrier(回环栅栏)方法
[8] 使用线程的Semaphore(信号量)方法
你这都是两个不同的request请求了
其实完全没必要select一下
update里可以写where条件,把没有值当做条件
如果执行结果,受影响的行数为0,就说明没有真正更新
这根本用不到线程同步,也用不到事务