Почему мой синхронизированный метод не работает должным образом? - PullRequest
0 голосов
/ 02 июля 2018

У меня есть этот синхронизированный метод, который печатает счетчик, у меня есть 4 потока, поэтому я ожидаю, что конечное значение моего счетчика будет 400000, так как мой счетчик является статической переменной.

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

Ниже мой код:

class MyThread implements Runnable{

    private static int counter=1;
    @Override
    public void run() {
        try {
            this.syncMethod();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public synchronized void syncMethod() throws InterruptedException{
        for(int i=0;i<100000;i++){
            System.out.println(Thread.currentThread().getName()+" : "+counter++);
        }
    }
}

public class MyController {
    public static void main(String[] args) throws InterruptedException {
        Runnable r1=new MyThread();
        Runnable r2=new MyThread();
        Runnable r3=new MyThread();
        Runnable r4=new MyThread();
        Thread t1;
        Thread t2;
        Thread t3;
        Thread t4;
        t1=new Thread(r1,"Thread 1");
        t2=new Thread(r2,"Thread 2");
        t3=new Thread(r3,"Thread 3");
        t4=new Thread(r4,"Thread 4");

        t2.start();
        t1.start();
        t3.start();
        t4.start();
    }
}

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

Ответ Эрвина Болвидта является правильным для решения вашей проблемы. В качестве другого способа безопасного увеличения статического общего счетчика в нескольких потоков вы можете обратиться к AtomicLong .

Определите это так:

private static AtomicLong counter = new AtomicLong();

Увеличивать его как:

counter.getAndIncrement();

И в итоге получите результат:

counter.get();
0 голосов
/ 02 июля 2018

синхронизированное ключевое слово в нестатических методах означает точно синхронизировать меня для этих методов: эти два кода являются строгим эквивалентом:

public synchronised void dojob(){
     //the job to do 
}

et

public void dojob(){
     synchronised (this){
     //the job to do 
     }
}

в вашем случае ваши синхронизированные методы синхронизируются на разных объектах (t1, t2, t3 и t4), поэтому не блокировали их друг друга. лучшее решение заключается в том, что ваш поток будет использовать общий объект для синхронизации друг с другом. другой момент, лучше всегда вернуть поток, чтобы выполнить этот вызов join, это код, который делает то, что вы хотите с этими 2 исправлениями

class MyThread implements Runnable {

    public static class JobDoer {

        public synchronized void syncMethod() throws InterruptedException {
            for (int i = 0; i < 100000; i++) {
                System.out.println(Thread.currentThread().getName() + " : " + counter++);
            }
        }
    }

    private static int counter = 1;

    public MyThread(JobDoer doer) {
        this.doer = doer;
    }

    private JobDoer doer;

    @Override
    public void run() {
        try {
            doer.syncMethod();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        JobDoer doer = new JobDoer();
        Thread t1 = new Thread(new MyThread(doer), "Thread 1");
        Thread t2 = new Thread(new MyThread(doer), "Thread 2");
        Thread t3 = new Thread(new MyThread(doer), "Thread 3");
        Thread t4 = new Thread(new MyThread(doer), "Thread 4");

        t2.start();
        t1.start();
        t3.start();
        t4.start();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
    }
}
0 голосов
/ 02 июля 2018

Переменная static, но метод, который вы synchronized, не static. Это означает, что он получит монитор в текущем экземпляре, и у каждого потока будет свой текущий экземпляр.

Простым решением является также метод syncMethod static; в этом случае он будет блокировать монитор, общий для всех экземпляров класса MyThread:

public static synchronized void syncMethod()
...