Java 原子参考<;ArrayList>;困难和备选方案
因此,在我为好玩而编写的各种程序中,我遇到了并发修改异常 在我天真地试图解决这个问题时,我使用了一个原子而不是某种并发集合。我有点熟悉为什么这是套管错误。从本质上讲,ArrayList的各个元素是不同步的,可以由不同的线程随意修改Java 原子参考<;ArrayList>;困难和备选方案,java,concurrency,Java,Concurrency,因此,在我为好玩而编写的各种程序中,我遇到了并发修改异常 在我天真地试图解决这个问题时,我使用了一个原子而不是某种并发集合。我有点熟悉为什么这是套管错误。从本质上讲,ArrayList的各个元素是不同步的,可以由不同的线程随意修改 有人能给我总结一下吗 尝试对集合进行原子引用时发生了哪些错误 对数组或列表的原子引用的合法用例是什么 对于存储可由多个线程使用的游戏实例,有哪些更好的替代方案 使用AtomicReference存储对象(如集合)不足以使其线程安全。事实上,如果放入AtomicRef
有人能给我总结一下吗
使用
AtomicReference
存储对象(如集合)不足以使其线程安全。事实上,如果放入AtomicReference
的对象不是线程安全的,例如ArrayList
,那么如果有多个线程试图同时修改其状态,那么使用它仍然是不安全的。因此,好的方法仍然是在AtomicReference
中放入一个不可变的对象,这样它的状态就不能再被多个线程修改了。例如,对于集合,您可以使用类型为Collections.unmodifiable*
的方法,例如Collections.unmodifiableList(List)
的列表,以便将集合的不可变版本放入AtomicReference
中
如果您需要线程安全的集合,您应该查看包
java.util.concurrent
中的类,您会发现集合本机是线程安全的。例如,如果您主要阅读并且很少修改列表
,则可以使用线程安全且高效的列表。我认为您混淆了ConcurrentModification的含义
最常见的情况是在循环中迭代集合并修改它时
例如,如果您执行以下操作
public static void main(String[] args) {
List<String> l = new LinkedList<>();
for(int i=0; i < 100; i++) {
l.add("banana"+i);
}
for (String s : l) {
if("banana10".equals(s)) {
l.remove(s);
}
}
}
publicstaticvoidmain(字符串[]args){
列表l=新的LinkedList();
对于(int i=0;i<100;i++){
l、 加上(“香蕉”+i);
}
for(字符串s:l){
如果(“banana10”。等于){
l、 移除(s);
}
}
}
…这将给您一个ConcurrentModificationException。注意,我没有产生任何线程
正确的方法如下:
public static void main(String[] args) {
List<String> l = new LinkedList<>();
for(int i=0; i < 100; i++) {
l.add("banana"+i);
}
for (Iterator<String> iterator = l.iterator(); iterator.hasNext();) {
String s = iterator.next();
if("banana10".equals(s)) {
iterator.remove();
}
}
}
publicstaticvoidmain(字符串[]args){
列表l=新的LinkedList();
对于(int i=0;i<100;i++){
l、 加上(“香蕉”+i);
}
for(迭代器迭代器=l.Iterator();迭代器.hasNext();){
字符串s=迭代器.next();
如果(“banana10”。等于){
iterator.remove();
}
}
}
请注意,在循环集合时使用迭代器修改集合
所以,我认为您没有并发问题
如果希望使集合线程安全,则需要查看线程安全的语义。如果希望允许多个线程访问同一个集合,那么ConcurrentList将是一个很好的方法。如果您想要一个原子设置的列表引用,作为一个整体,您可以使用原子引用。“到集合上的集合”?这是什么意思?我建议添加防御副本解决方案ConcurrentList?从哪个库?您可以通过Collections.synchronizedList()使列表安全,也可以使用向量。由
集合生成的列表。不可修改列表(List)
不是不可变的。包装列表仍可能更改。对于真正不可变的列表,使用例如番石榴的不可变列表
。