我想知道使会话 bean 线程安全的最佳实践是什么。
假设我有这个会话 bean 及其服务:
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
class Cart {
private HashSet<Item> items = new HashSet<Item>();
private int counter = 0;
public HashSet<Item> getItems() {
return items;
}
public int getCounter() {
return counter;
}
}
@Service
class CartService {
@Autowired
private Cart cart;
public void addItem(Item item) throws FullException {
if (cart.getCounter() > 1234) {
throw new FullException();
}
cart.getItems().add(item);
}
}
上面的代码不是线程安全的,当多个线程(同一会话的,例如通过异步 Ajax 请求)执行CartService.addItem(Item)
.
我想我不是第一个遇到这个问题的人,但我的研究并没有让我找到最佳实践。
我能做的最糟糕的事情是同步 addItem() 因为 CartService 由多个会话共享。在我看来,在购物车上同步CartService.addItem()
似乎同样糟糕,因为购物车是一个代理 bean。据我了解,所有会话仍将在同一个对象上同步。
一种可接受的解决方案似乎是 in 上的同步Cart.getItems()
块CartService.addItem()
:
@Service
class CartService {
@Autowired
private Cart cart;
public void addItem(Item item) {
synchronized(cart.getItems()) {
if (cart.getCounter() > 1234) {
throw new FullException();
}
cart.getItems().add(item);
}
}
}
有没有最佳实践?也许春天可以为这个问题提供一些东西?