- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如果我在多线程环境中有一个组件列表,并且如果我对此列表执行除 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/
我是一名优秀的程序员,十分优秀!