Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 原子参考<;ArrayList>;困难和备选方案_Java_Concurrency - Fatal编程技术网

Java 原子参考<;ArrayList>;困难和备选方案

Java 原子参考<;ArrayList>;困难和备选方案,java,concurrency,Java,Concurrency,因此,在我为好玩而编写的各种程序中,我遇到了并发修改异常 在我天真地试图解决这个问题时,我使用了一个原子而不是某种并发集合。我有点熟悉为什么这是套管错误。从本质上讲,ArrayList的各个元素是不同步的,可以由不同的线程随意修改 有人能给我总结一下吗 尝试对集合进行原子引用时发生了哪些错误 对数组或列表的原子引用的合法用例是什么 对于存储可由多个线程使用的游戏实例,有哪些更好的替代方案 使用AtomicReference存储对象(如集合)不足以使其线程安全。事实上,如果放入AtomicRef

因此,在我为好玩而编写的各种程序中,我遇到了并发修改异常

在我天真地试图解决这个问题时,我使用了一个原子而不是某种并发集合。我有点熟悉为什么这是套管错误。从本质上讲,ArrayList的各个元素是不同步的,可以由不同的线程随意修改


有人能给我总结一下吗

  • 尝试对集合进行原子引用时发生了哪些错误
  • 对数组或列表的原子引用的合法用例是什么
  • 对于存储可由多个线程使用的游戏实例,有哪些更好的替代方案


  • 使用
    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)
    不是不可变的。包装列表仍可能更改。对于真正不可变的列表,使用例如番石榴的
    不可变列表