hibernate 多线程update·死锁(locked timeout)
描述:
hibernate+spring+springmvc 配置了openSessionInView,先查询,查询后的结果集交给另一个线程更新字段, 少量数据正常,大量数据时死锁。
问题:关键是hibernate查询出来的结果集是数据库实体,队友没有将实体转化成bo,在主线程中修改了实体中的字段;交给新线程更新实体数据集后,由于主线程中修改了实体的字段,导致数据被加锁,主线程由于数据量较大导致事务没有及时提交,子线程中同时请求了数据的行锁,导致锁超时。本身是由代码的bug造成的,用bo阻断可以解决或者把修改任务都交给子线程即可解决。
原子类并发set非线程安全
错误代码
AtomicInteger i = new AtomicInteger(0);
List<Integer> list = Collections.synchronizedList(new ArrayList<>(100));
for(int num=0;num<1000;num++){
list.add(num);
}
list.parallelStream().forEach(nu->{
i.compareAndSet(i.get(),i.get()+2);
});
System.out.println(i.get());
问题就出在 i.compareAndSet(i.get(),i.get()+2);中的i.get()上,在并行时可能会在某几个线程中获取到的i的值相同而导致线程安全问题。
解决思路是吧对i的操作转变为原子操作 i.getAndAdd(2);交由UNSAFE类去做判断。
修改后
AtomicInteger i = new AtomicInteger(0);
List<Integer> list = Collections.synchronizedList(new ArrayList<>(100));
for (int num = 0; num < 1000; num++) {
list.add(num);
}
list.parallelStream().forEach(nu -> {
i.getAndAdd(2);
});
System.out.println(i.get());