java是CopyOnWriteArrayList,足以在Servlet会话范围内保持购物车线程安全
是CopyOnWriteArrayList列表足以用作购物车的集合。据我所知,它是线程安全的,并且当迭代过程中另一个线程删除一个产品时,迭代器保证不会抛出ConcurrentModificationException
。例如:
...
CopyOnWriteArrayList<Product> products = (CopyOnWriteArrayList<Product>)session.getAttribute("PRODUCTS");
products.addIfAbsent(aProduct);
...
顺便说一句,我发现同步方法是使用synchronized(session){…}但是,当我使用this文章中提供的购物车时,需要在任何地方同步会话访问时,这就有点难看了
# 1 楼答案
否,因为这取决于需要同步的内容。想想什么不能同时发生
您不会得到
ConcurrentModificationException
,因为您对列表所做的每一次修改都会创建列表的副本。迭代的线程将使用最新的副本。但该线程不能假设一个产品在看到它时仍然在列表中。它可能已在最新版本中删除# 2 楼答案
或者在访问购物车收藏时,在所有地方使用“重型火炮”,如以下
非常感谢之前的回答
# 3 楼答案
我认为在你描述的场景中,你可以使用CopyOnWriteArrayList。 它有足够的保证作为线程安全的实现工作,包括 可见度是的,当您调用iterate时,它确实给出了数据的快照。 但总有一个竞争条件,当你在阅读之前删除它,或者在删除之前阅读它。CopyOnWriteArrayList是一个很好的实现 可在读取>>>;写,我认为购物车用例就是这样
只是在迭代时,您不会看到更改(写入操作)。你应该明白,没有什么是免费的,如果你想在遍历过程中看到变化,你需要正确地同步你的每一次迭代与任何写操作,这将损害性能。相信我,你将一无所获。大多数并发数据结构在迭代时给出弱一致状态,请参见(ConcurrentSkipListSet)。 所以使用CopyOnWriteArrayList和ConcurrentSkipListSet中的任何一种都可以。 我认为集合更适合您的用例,即避免重复订单
# 4 楼答案
你需要了解
CopyOnWriteArrayList
提供了什么它为您提供了一个快照,而不提供后端阵列的实时视图
它削弱了可见性的契约,它说你不会得到
ConcurrentModificationException
,但也说如果其他线程删除了一些元素,效果对正在迭代的其他线程可能是不可见的,因为在添加或删除时,原始数组不会发生变异或被触碰,而在每次变异备份数组的操作中都会创建一个新的数组视情况而定
如果这种行为在您的场景中是可以接受的,那么您可以使用它,但是如果您想要可见性保证,您可能必须使用显式锁定