Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.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的同一副本时,为什么没有ConcurrentModificationException_Java_Multithreading_Iterator_Concurrentmodification - Fatal编程技术网

Java 当一个线程迭代(使用迭代器)而另一个线程修改非线程安全ArrayList的同一副本时,为什么没有ConcurrentModificationException

Java 当一个线程迭代(使用迭代器)而另一个线程修改非线程安全ArrayList的同一副本时,为什么没有ConcurrentModificationException,java,multithreading,iterator,concurrentmodification,Java,Multithreading,Iterator,Concurrentmodification,一些背景: 当使用Iterator对集合进行迭代时,可能会出现java.util.ConcurrentModificationException,因为在创建Iterator对象时,会捕获集合或数组列表的修改计数(modCount),并在每次迭代时使用Iterator.next()检查modCount是否已更改,如果已更改,则抛出java.util.ConcurrentModificationException 在创建迭代器对象时(从ArrayList的iterator实现): int expec

一些背景:
当使用
Iterator
对集合进行迭代时,可能会出现
java.util.ConcurrentModificationException
,因为在创建
Iterator
对象时,会捕获集合或数组列表的修改计数(
modCount
),并在每次迭代时使用
Iterator.next()
检查
modCount
是否已更改,如果已更改,则抛出
java.util.ConcurrentModificationException

在创建迭代器对象时(从
ArrayList
iterator
实现):
int expectedModCount=modCount

调用下面的方法
Iterator.next()
,该方法引发异常(来自
ArrayList
Iterator
实现):

我可以使用以下代码很好地复制它:

List<String> stringList = new ArrayList<String>();
                stringList.add("a");
                stringList.add("b");
                stringList.add("c");
                Iterator<String> iterator = stringList.iterator();
                System.out.println("Got iterator object");
                while (iterator.hasNext()) {
                    String player = iterator.next();
                    player.toString();
                    System.out.println("UpperCase: " + player.toUpperCase());
                    iterator.remove();
                    stringList.add("a1"); //This is root cause of exception.
                }

在另一个线程中获得
迭代器并开始迭代后,如何保证调用一个线程中的
添加
删除
?提示:竞争条件。
Thread.start()
需要很长且不可预测的时间(相对而言,从计算角度来说)。在您更改列表之前,您没有任何代码可以保证迭代开始。@SotiriosDelimanolis谢谢。我知道了,我不知怎么错过了。我的错。我在while循环中休眠了第二个线程1秒,第一个线程也休眠了1秒,这样就没有了不必要的争用条件,我得到了异常。我将删除这个问题。@aff我实际上在while循环的第一个线程中有睡眠,但我没有发布它。我错过了第二个线程。索蒂里奥斯睁开了我的眼睛,我明白了。谢谢你的留言。我将删除这个问题。请注意,即使使用了正确的交错,因为modCound不是易失性的,所以您没有可见性保证,并且第一个线程可能看不到第二个线程所做的修改。此行为试图帮助您检测错误,但不能提供任何保证。如何保证在另一个线程中获取
迭代器并开始迭代后,调用一个线程中的
添加
删除
?提示:竞争条件。
Thread.start()
需要很长且不可预测的时间(相对而言,从计算角度来说)。在您更改列表之前,您没有任何代码可以保证迭代开始。@SotiriosDelimanolis谢谢。我知道了,我不知怎么错过了。我的错。我在while循环中休眠了第二个线程1秒,第一个线程也休眠了1秒,这样就没有了不必要的争用条件,我得到了异常。我将删除这个问题。@aff我实际上在while循环的第一个线程中有睡眠,但我没有发布它。我错过了第二个线程。索蒂里奥斯睁开了我的眼睛,我明白了。谢谢你的留言。我将删除这个问题。请注意,即使使用了正确的交错,因为modCound不是易失性的,所以您没有可见性保证,并且第一个线程可能看不到第二个线程所做的修改。此行为试图帮助您检测bug,但不能提供任何保证。
List<String> stringList = new ArrayList<String>();
                stringList.add("a");
                stringList.add("b");
                stringList.add("c");
                Iterator<String> iterator = stringList.iterator();
                System.out.println("Got iterator object");
                while (iterator.hasNext()) {
                    String player = iterator.next();
                    player.toString();
                    System.out.println("UpperCase: " + player.toUpperCase());
                    iterator.remove();
                    stringList.add("a1"); //This is root cause of exception.
                }
private static void iteratorException() {
    final List<String> stringList = new ArrayList<String>();

    Thread thread = new Thread(){
        @Override
        public void run() {
            System.out.println("T1");
            stringList.add("a");
            stringList.add("b");
            stringList.add("c");
            Iterator<String> iterator = stringList.iterator();
            System.out.println("Got iterator object");
            while (iterator.hasNext()) {
                String player = iterator.next();
                player.toString();
                System.out.println("UpperCase: " + player.toUpperCase());
                iterator.remove();
                //stringList.add("a1");
            }
        }
    };

    Thread thread2 = new Thread(){
        @Override
        public void run() {
            System.out.println("T2");
            stringList.add("d");
            stringList.remove("a");
            System.out.println("finished T2");
        }
    };

    thread.start();
    thread2.start();
}