Потоки работают последовательно, а не параллельно - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь изучить параллелизм в Java, но что бы я ни делал, 2 потока выполняются последовательно, а не параллельно, поэтому я не могу воспроизвести распространенные проблемы параллелизма, описанные в руководствах (например, помехи потоков и ошибки согласованности памяти). Пример кода:

public class Synchronization {
static int v;

public static void main(String[] args) {

    Runnable r0 = () -> {
        for (int i = 0; i < 10; i++) {
            Synchronization.v++;
            System.out.println(v);
        }
    };

    Runnable r1 = () -> {
        for (int i = 0; i < 10; i++) {
            Synchronization.v--;
            System.out.println(v);
        }
    };

    Thread t0 = new Thread(r0);
    Thread t1 = new Thread(r1);
    t0.start();
    t1.start();

}

}

Это всегда дает мне результат, начиная с 1 и заканчивая 0 ( независимо от длины цикла ). Например, код выше дает мне каждый раз:

1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1 0

Иногда второй поток запускается первым, и результаты такие же, но отрицательные, поэтому он все еще работает в последовательном режиме.

Пробовал в Intellij и Eclipse с одинаковыми результатами. Процессор имеет 2 ядра, если это имеет значение.

ОБНОВЛЕНИЕ: оно наконец стало воспроизводимым с огромными циклами (начиная с 1_000_000), но все же не каждый раз и только с небольшим количеством окончательного расхождения. Также кажется, что выполнение операций в циклах «тяжелее», например, печать имени потока делает его более воспроизводимым. Ручное добавление sleep в thread также работает, но, так сказать, делает эксперимент менее чище. Кажется, причина не в том, что первый цикл завершается до запуска второго, потому что я вижу, как оба цикла печатаются в консоль, продолжая работать, и все еще дают мне 0 в конце. Причины, похоже, больше похожи на гонку потоков по одной и той же переменной. Я углублюсь в это, спасибо.

Ответы [ 3 ]

0 голосов
/ 13 сентября 2018

Похоже, что первый запущенный поток просто никогда не дает шанс секунде в Thread Race взять переменную / секунду, просто никогда не хватает времени даже на запуск (не могу сказать наверняка), поэтому второй почти * всегда будетожидание завершения первого цикла.

Некоторые тяжелые операции смешивают результат: TimeUnit.MILLISECONDS.sleep(100);

* это не всегда верно, но вам повезло в ваших тестах

0 голосов
/ 20 сентября 2018

Это называется счастливым временем согласно Брайану Гетцу (Автор Java-параллелизма на практике).Поскольку синхронизация со статической переменной v отсутствует, ясно, что этот класс не является поточно-ориентированным.

0 голосов
/ 13 сентября 2018

Запуск потока - это тяжеловесная операция, а это значит, что выполнение займет некоторое время.В связи с тем, что к моменту запуска второго потока первый завершается.

Причина, по которой иногда он находится в «обратном порядке», связана с тем, как работает планировщик потоков.Спецификации не гарантируют порядок выполнения потоков - имея это в виду, мы знаем, что второй поток может запускаться первым (и заканчивать)

Увеличить счетчик итераций до значения, такого как 10000, и посмотреть, чтобудет потом

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