gpt4 book ai didi

java - 线程安全简单

转载 作者:行者123 更新时间:2023-12-01 12:20:27 24 4
gpt4 key购买 nike

如果我在多线程环境中有一个组件列表,并且如果我对此列表执行除 add(在本例中我在列表上使用关键字同步)和 get(组件调用的方法是线程)之外的任何操作安全),那是线程安全的吗?

public class Test {

private final ArrayList<Component> myContainer = new ArrayList<Component>();

public void add(Component){
synchronized(myContainer){
myContainer.add(Component)
}
}

public void useComponents()
{
for(Component c : myContainer)
c.use(); // method thread-safe
}

// no other operations on myContainer
}

最佳答案

在当前形式中,它不是线程安全的:useComponents 方法可以由一个线程执行。同时,另一个线程可以调用add,从而在迭代时修改集合。 (此修改可能发生在对 c.use() 的两次调用之间,因此 use() 方法是线程安全的这一事实不会在这里为您提供帮助)。

严格来说,这甚至不限于多线程:如果c.use()内部调用test.add(someOtherComponent) (即使它是在同一个线程中完成的!)这会抛出 ConcurrentModificiationException 异常,因为集合在迭代时会被修改。

线程安全(没有针对并发修改的安全性)可以通过简单地将迭代包装到 synchronized block 中来实现:

public void useComponents()
{
synchronized (myContainer)
{
for(Component c : myContainer)
c.use(); // method thread-safe
}

}

但是,这仍然有可能出现 ConcurrentModificationException。 c.use() 调用很可能不会(也不应该)修改包含该组件的集合(否则,人们可能会质疑总体设计)。

如果您希望允许 c.use() 调用修改集合,您可以将集合替换为 CopyOnWriteArrayList:

private final List<Component> myContainer = 
new CopyOnWriteArrayList<Component>();

然后您甚至可以完全删除同步。但您应该意识到其中的含义:列表的内容将在每次修改期间复制(因此得名...)。这通常用于您有一个经常迭代但很少修改的小集合的情况。 (各种形式的听众就是一个典型的例子)。

关于java - 线程安全简单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26699101/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com