Упорядочение в одновременном чтении и записи в коллекции в потоках в Java - PullRequest
0 голосов
/ 11 июля 2019

Я пробую код, чтобы увидеть, что произойдет, если поток изменяет коллекцию, в то время как другие потоки читают коллекцию.Вот код

package threading;

import java.util.ArrayList;

public class ReadAndWrite {

    static ArrayList<Integer> coll = new ArrayList<Integer>();

    public static void main(String[] args) {
        coll.add(1);
        coll.add(3);
        coll.add(5);

    Thread t = new Thread() {
        public void run(){
            coll.add(2);
            coll.add(6);
            coll.add(8);
        }
    };
    Thread t1 = new Thread() {
            public void run(){
                System.out.println(" collection is "+coll + " and size is "+coll.size());
            }
    };
    Thread t2 = new Thread() {
        public void run(){
            System.out.println(" collection is "+coll+ " and size is "+coll.size());
        }
};
Thread t3 = new Thread() {
    public void run(){
        System.out.println(" collection is "+coll+ " and size is "+coll.size());
    }
};
Thread t4 = new Thread() {
    public void run(){
        System.out.println(" collection is "+coll+ " and size is "+coll.size());
    }
};
Thread t5 = new Thread() {
    public void run(){
        System.out.println(" collection is "+coll+ " and size is "+coll.size());
    }
};
t.start();

t1.start();

t2.start();
t3.start();

t4.start();
t5.start();

        }

        }

Когда я начинаю сначала писать поток, это ответ, который я получаю все время.

collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5, 2, 6, 8] and size is 6

Как только я изменяю порядок, как показано ниже, все идет наперекосяк в ответ

 t1.start();
t.start();
t2.start();
t3.start();

t4.start();
t5.start();

Ответ

 collection is [1, 3, 5] and size is 3
 collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5] and size is 3
 collection is [1, 3, 5] and size is 3

Если мы продолжим экспериментировать с порядкоммы увидим ошибку, подобную приведенной ниже

Exception in thread "Thread-1"  collection is [1, 3, 5, 2, 6, 8] and size is 6Exception in thread "Thread-2" 
 collection is [1, 3, 5, 2, 6, 8] and size is 6
 collection is [1, 3, 5, 2, 6, 8] and size is 6
java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at java.util.AbstractCollection.toString(AbstractCollection.java:461)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at threading.ReadAndWrite$3.run(ReadAndWrite.java:28)
java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at java.util.AbstractCollection.toString(AbstractCollection.java:461)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at threading.ReadAndWrite$2.run(ReadAndWrite.java:23)

Вопросы:

  1. Кажется, что здесь очевидным решением является синхронизация или блокировка, но почему первый запуск потока записи дает нам одинаковые результаты, потоки должны работать не по порядку, не так ли?
  2. Я думал, что одновременная запись - это проблема, но даже когда у нас только один поток записи, мы сталкиваемся с ошибками, почему?

Буду глубоко признателен за указания по вышеуказанному сценарию, заранее спасибо.Sid

1 Ответ

0 голосов
/ 11 июля 2019

Ответ на вопрос 1: Ваше утверждение о том, что потоки должны быть не в порядке, не является точным.Несколько моментов: 1. Java не определяет, как реализованы потоки, и, следовательно, они могут быть реализованы с использованием собственных потоков или зеленых потоков, зеленые потоки являются только конструкцией Java, запланированной JVM.Реализация потоков может повлиять на поведение во время выполнения.JVM в Linux и Windows использует собственные потоки.2. Когда вы запускаете поток, он выполняется немного, а затем прерывается и запускается другой поток.Ваши потоки делают так мало, что когда вы запускаете поток записи, он запускается до завершения, прежде чем планируются любые другие потоки.

Исходя из вышеизложенного, вы не можете делать какие-либо предположения о том, когда поток будет выполняться и сколько операторов они будут выполнять, это зависит от множества различных переменных, особенно при использовании собственных потоков, которые запланированы ОС.

Ответ на вопрос 2. Когда вы перебираете ArrayList, метод итератора next () отслеживает modCount.Если вы измените коллекцию, добавив или удалив элемент, то значение modCount изменится и не будет соответствовать ожидаемому значению modCount, поэтому Iterator сгенерирует исключение ConcurrentModificationException.Следовательно, даже если у вас есть только один модуль записи, если у вас есть параллельный модуль чтения, вы можете получить исключение ConcurrentModificationException

CopyOnWriteArrayList является поточно-ориентированной реализацией ArrayList

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...