[英]Is CopyOnWriteArrayList enough for keeping shopping cart thread-safe in Servlet Session scope
CopyOnWriteArrayList列表是否足以用作购物车的集合。 据我了解,它是线程安全的,并且在迭代期间另一个线程删除产品时,保证迭代器不会引发ConcurrentModificationException
。 例如:
...
CopyOnWriteArrayList<Product> products = (CopyOnWriteArrayList<Product>)session.getAttribute("PRODUCTS");
products.addIfAbsent(aProduct);
...
PS我发现使用同步(会话)的同步方法{...}但接缝有点丑,当我需要的时候我的购物推车那样工作提供无处不在同步会话访问本文章
您需要了解CopyOnWriteArrayList
提供的内容。
它削弱了可见性的约束,它说您将不会获得ConcurrentModificationException
而且还说如果其他线程删除了某些元素,则该效果对于正在迭代的其他线程将不可见,因为在添加或删除时,原始数组不可见。更改或触摸,并在使支持数组发生更改的每个操作上创建一个新操作。
CopyOnWriteArrayList列表是否足以用作购物车的集合。
要看。
如果这种情况在您的方案中是可以接受的,那么您可以使用它,但是如果要保证可见性,则可能必须使用显式锁定。
CopyOnWriteArrayList列表是否足以用作购物车的集合
否,因为它取决于您需要同步的内容。 考虑一下不能同时发生的事情。
据我了解,它是线程安全的,并且在迭代期间另一个线程删除产品时,保证迭代器不会引发ConcurrentModificationException。
您不会得到ConcurrentModificationException
因为您对列表所做的每次修改都会创建列表的副本。 迭代的线程将使用最新副本。 但是,该线程无法在看到产品时就假定该产品实际上仍在列表中。 在最新版本中可能已将其删除。
或者在访问购物车集合时,在所有地方都使用如下所示的“重炮”。
AtomicReference<List<Product>> productListRef =
AtomicReference<List<Product>>)session.getAttribute("PRODUCTS");
List<Product> oldList;
List<Product> newList;
do {
oldList = productListRef.get();
newList = new ArrayList<>(oldList);
newList.add(aProduct);
} while (!ref.compareAndSet(oldList, newList));
非常感谢您之前的回答!
我认为您在所描述的场景中使用CopyOnWriteArrayList很好。 它有足够的保证作为线程安全的实现(包括可见性)来工作。 是的,的确,当您调用迭代时,它提供了数据的快照。 但是总是有一个竞争条件,当您在读取之前删除它或在删除之前读取它时.CopyOnWriteArrayList是一个很好的实现,可以在读取>>> writes的地方使用,我认为在购物车用例中就是这种情况。
只是在迭代时您不会看到更改(写操作)。 您应该了解没有什么是免费的,如果要在遍历时看到更改,则需要正确地将每次迭代与任何写入操作同步,这会影响性能。 相信我,你将一无所获。 大多数并发数据结构在迭代时会给出弱一致的状态,请参见(ConcurrentSkipListSet)。 因此,使用CopyOnWriteArrayList,ConcurrentSkipListSet都是不错的选择。 我认为集合对您的用例更好,即避免重复订单..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.