Почему этот код не является потокобезопасным? - PullRequest
9 голосов
/ 25 ноября 2011

В приведенном ниже фрагменте кода объявление метода doThings () как статического сделает класс потокобезопасным. Является ли причиной этого то, что если запущено несколько потоков TestSeven и поскольку x является статической переменной, может возникнуть условие гонки?

public class TestSeven extends Thread{

    private static int x;

    public synchronized void doThings(){
        int current = x;
        current++;
        x = current;
    }

    public void run(){
        doThings();
    }

    public static void main(String args[]){
        TestSeven t = new TestSeven();
        Thread thread = new Thread(t);
        thread.start();
    }
}

Ответы [ 5 ]

16 голосов
/ 25 ноября 2011

Да, именно так.synchronized природа doThings только останавливает его от одновременного вызова несколькими потоками в одном и том же экземпляре .Переменная x является общей для global , а не для каждого отдельного экземпляра, поэтому она небезопасна.

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

1 голос
/ 25 ноября 2011

Вы синхронизируете свой код на this, то есть на этом экземпляре TestSeven.x является статическим, поэтому он не будет заблокирован.Вот почему в разных случаях вы можете получить доступ к одному и тому же x.Чтобы заблокировать этот атрибут, вам необходимо выполнить синхронизацию с классом.

1 голос
/ 25 ноября 2011

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

1 голос
/ 25 ноября 2011

Просто добавьте, что если вы объявите метод doThings статическим, он будет синхронизироваться по блокировке класса, а не по блокировке экземпляра, поэтому он будет пуленепробиваемым.

1 голос
/ 25 ноября 2011

Я думаю, что если метод не является статическим, каждый объект TestSeven будет синхронизироваться с использованием своей собственной блокировки - так что будет один поток на блокировку, и ни одному из них не придется ждать другого потока.Если метод объявлен как статический, я напоминаю, что они блокируются соответствующим объектом Class.

...