синхронизированный метод не работает как блокировка ?? почему бы не сделать блокировку на счет - PullRequest
0 голосов
/ 03 сентября 2018

Как показано в приведенном ниже коде, я использую интенсивную блокировку (монитор) для моей переменной count, и одновременно можно получить доступ только к одной Thread, сделав метод synchIncrement() синхронизированным. Тогда значение O / P должно составлять 20000, но все равно будет некоторое значение разницы во времени.

Почему?

public class SynchBlockThread {
    private int count = 0;

    private synchronized void synchIncrement() {
        count++;
    }

    public static void main(String[] args) {
        SynchBlockThread sBT = new SynchBlockThread();
        sBT.doWork();

    }

    private  void doWork() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i<10000; i++) {
                    synchIncrement();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i<10000; i++) {
                    synchIncrement();
                }
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }
}

enter image description here

Ответы [ 2 ]

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

Синхронизированный метод делает свою работу правильно. Проблема в том, что вы не ждете второго Thread. count может быть напечатано до , второй поток завершается, поэтому вы также должны добавить t2.join();:

try {
    t1.join();
    t2.join();
} catch (InterruptedException e) { ... }

Давайте рассмотрим более интересную версию вашего метода:

private void doWork() throws InterruptedException {
    final int n = 2;

    final CountDownLatch latch = new CountDownLatch(n);
    final ExecutorService service = Executors.newFixedThreadPool(n);
    final Runnable task = () -> {
        for (int i = 0; i < 10000; i++) {
            synchIncrement();
        }
        latch.countDown();
    };

    for (int i = 0; i < n; ++i) {
        service.execute(task);
    }

    latch.await();
    service.shutdown();
    System.out.println(count);
}

Я ввел ExecutorService фиксированного размера, чтобы не создавать темы самостоятельно. Я написал CountDownLatch, чтобы знать, когда все задачи завершат выполнение, чтобы я мог закрыть службу и распечатать результат.

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

Довольно трудно определить.

В конце метода doWork() вы присоединяетесь к Thread t1 дважды, поэтому Thread t2 все еще выполняет свою работу, когда выводится результат.

Чтобы выразить это в коде:

try {
    t1.join();
    t1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

вместо этого должно быть

try {
    t1.join();
    t2.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
...