Потоки и синхронизированные методы - PullRequest
2 голосов
/ 09 ноября 2011

У меня есть следующий код:

public class MyThread extends Thread {
    private int i;
    public static int sum=0;
    public MyThread(int k){
      i=k;
    }




    public static void main(String[] args) throws InterruptedException{

       Thread t=new MyThread(1);
       Thread s=new MyThread(2);
       Thread p=new MyThread(3);
       t.start();
       s.start();       
    }


public synchronized void doSomething(){
    for(int i=0; i<100000; i++){
        System.out.println(this.i);
    }

}

    @Override
    public void run() {
        doSomething();

    }
}

doSomething синхронизирован.почему вывод случайный?Мое предположение, что синхронизированный метод будет таким же, как синхронизированный блок, но выход блока будет синхронизированным, а метод - нет.

Ответы [ 3 ]

9 голосов
/ 09 ноября 2011

Ключевое слово synchronized предотвращает чередование синхронизированных вызовов методов на того же объекта .Это не предотвращает чередование вызовов методов на различных объектах.Поскольку у вас есть три разных объекта, три вызова могут выполняться одновременно.

Вам необходимо выполнить синхронизацию на одном объекте, который используется всеми тремя потоками.

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

Синхронизация по методам выполняется только для вызовов одного и того же объекта.Вы создаете два разных объекта (два потока).

0 голосов
/ 09 ноября 2011

Блокировка, используемая методами synchronized, связана с экземпляром класса MyThread. Поскольку каждый поток имеет свой собственный экземпляр MyThread, каждый поток синхронизируется с собственной блокировкой.

Если вы хотите синхронизировать все потоки, вы можете сделать что-то вроде:

public class MyThread extends Thread {

    private static final Object sharedLock = new Object();

    public void doSomething() {
      synchronized(sharedLock) {
        for(int i=0; i<100000; i++) {
          System.out.println(this.i);
        }
      }
    }
    ...
 }

Альтернативой является synchronize на MyThread.class, но я предпочитаю первый подход.

В комментариях вы говорите, что если вы измените свой код, чтобы использовать synchronized(this) в doSomething, это неожиданно сработает. Я уверен, что это не так. Возможно, это сработало случайно, но не будет работать многократно и надежно.

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