Integer number = sysProjectMapper.selectByMaxNumber();
sysProject.setNumber(Objects.nonNull(number) ? number + 1 : 1);
// 新增用户信息
int rows = sysProjectMapper.insertSysProject(sysProject);
一段代码,先查出某个字段的最大值,再插入的时候更新最大值。
高并发场景下,此处很有可能出现多个并发同时读取了同一个最大值的情况,导致插入同一个+1后的最大值。
因此此处要考虑到原子性,更改如下:
AtomicInteger number = new AtomicInteger(sysProjectMapper.selectByMaxNumber());
sysProject.setNumber(number.incrementAndGet());
// 新增用户信息
int rows = sysProjectMapper.insertSysProject(sysProject);
这行代码使用了AtomicInteger类来创建一个原子性计数器,其中的 new AtomicInteger(sysProjectMapper.selectByMaxNumber()) 语句会将从数据库中查询到的最大值作为初始值。
AtomicInteger类内部使用了Unsafe类的 CAS(Compare and Swap)操作来实现原子性。CAS操作会检查并更新某个内存地址中的值,如果该值与预期值相同,则更新为新的值。
在执行CAS操作期间,其他线程无法修改该值,从而保证了操作的原子性。
因此,这行代码可以确保从数据库查询最大值并将其作为计数器的初始值的操作是原子性的,不会被其他线程干扰或中断。