Некорректная работа synchronized java

156
21 октября 2019, 14:40

Изучаю Герберта Шилдта Java 8 Руководство для начинающих, и вопрос в следующем. Согласно книге метод synchronized обязан дать выполниться методу до завершения потока, а уже после запускать второй поток, что бы не было ошибок. Программа, просто находит сумму элементов массива.

public class SumArray {
    private int sum;
    synchronized int SumArray (int[] arr){
        sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
            System.out.println("Сумма "+ Thread.currentThread().getName() + " "+ sum);
            try {
                Thread.sleep(100);
            }catch (InterruptedException exc){
                System.out.println("Ошибочка");
            }
        }
        return sum;
    }
}
public class MyThread implements Runnable {
    Thread thrd;
    static SumArray sa = new SumArray();
    int a[];
    int answer;
    MyThread(String name, int[] arr){
        thrd = new Thread(this, name);
        a = arr;
        thrd.start();
    }
    @Override
    public void run() {
        int sum;
        System.out.println(thrd.getName() + "Запуск");
        answer = sa.SumArray(a);
        System.out.println("Сумма для " + thrd.getName()+" = " + answer);
        System.out.println(thrd.getName() + "Завершение");
        System.out.println("==================");
    }
}
class Sunc{
    public static void main(String[] args) {
        int a[] = {1,2,3,4,5};
        MyThread mt1 = new MyThread("Поток 1 ", a);
        MyThread mt2 = new MyThread("Поток 2 ", a);
    }
}

Результат должен быть похожим на это

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

Может я в чем-то не разобрался, или какая-то неточность в книге, возможно в переводе. Почему один из потоков вмешивается в выполнение другого.

Спасибо за внимание!

Answer 1

Потоки работают параллельно. Запуск цикла во втором потоке пошёл, как только первый вышел из синхронайзд блока.

У вас в synchronized только метод SumArray, т.е, гарантированно последовательно будет вызван цикл:

for (int i = 0; i < arr.length; i++)

У всего остального порядок не гарантирован.

Thread.sleep(100) тут, скорей всего, кроме переключение контекста ничего не делает. У вас поток всё ещё лочит весь synchronized блок. В итоге, цикл во втором потоке пошёл, как только первый вышел из синхронайзд блока.

READ ALSO
OpenGL ориентация

OpenGL ориентация

Каким образом можно сделать чтобы точка 0, 0 не была в низу слева, а чтобы она была вверху слева? Пробовал glOrtho(0D, 640D, 480D, 0D, 0D, 0D), но он ничего не делает

150
Можно ли сделать div такого вида? [закрыт]

Можно ли сделать div такого вида? [закрыт]

надо сделать див такого плана, и чтобы дочерние элементы были в закрашенной области, можно так сделать?

267
Как перезапустить таймер по кнопке

Как перезапустить таймер по кнопке

Есть код таймера всё отлично только не знаю как сделать чтобы по кнопке которую я задам он перезапускался

129
Экземпляры в ES6

Экземпляры в ES6

Назрел глупый вопрос, не могу сообразить как загуглить, поэтому пришел за помощью :)

101