Синхронизация между статическими методами класса - PullRequest
1 голос
/ 28 января 2011

Я написал следующий код:

public class ClassAndObjectLock {
 public static void main(String[] args) {
  new Thread(new EvenThread()).start();
  new Thread(new OddThread()).start();
 }
}

class EvenThread implements Runnable {
 public void run() {
  for (int i = 0; i < 10; i += 2) {
   CommonClass.printEvenNumber(i);
  }
 }
}

class OddThread implements Runnable {
 public void run() {
  for (int i = 1; i < 10; i += 2) {
   CommonClass.printOddNumber(i);
  }
 }
}

class CommonClass {
 public static void printEvenNumber(int num) {
  synchronized (CommonClass.class) {
   System.out.println("Even :" + num);
  }
 }

 public static void printOddNumber(int num) {
  synchronized (CommonClass.class) {
   System.out.println("Odd :" + num);
  }
 }
}

Когда я выполняю приведенный выше код, вывод следующий:

Even :0
Odd :1
Even :2
Odd :3
Even :4
Odd :5
Even :6
Odd :7
Even :8
Odd :9

Я не понимаю этот вывод.Насколько я понимаю, когда new Thread(new EvenThread()).start(); выполняется, он порождает поток класса EvenThread, который должен получить блокировку CommonClass и сохранить блокировку при себе, пока не напечатает все четные значения,Объект OddThread должен получить шанс только после того, как объект EvenThread закончен.Поэтому, по моему мнению, результат должен быть следующим:

Even :0  
Even :2
Even :4
Even :6
Even :8
Odd :1
Odd :3
Odd :5
Odd :7
Odd :9

Может ли кто-нибудь объяснить мне основную логику?

Ответы [ 2 ]

2 голосов
/ 28 января 2011

Согласно моему пониманию, когда новый поток (новый EvenThread ()). Start ();выполняется, он порождает поток класса EvenThread, который должен получить блокировку CommonClass и сохранить блокировку при себе, пока он не напечатает все четные значения.

Нет, это не так:

 public static void printOddNumber(int num) {
   synchronized (CommonClass.class) {
       System.out.println("Odd :" + num);
   }
 }

, который (поскольку метод является статическим для класса монитора), также может быть записан как

 public static synchronized void printOddNumber(int num) {
       System.out.println("Odd :" + num);
 }

Посмотрите на область действия синхронизированного блока: он печатает только один номер, а затем снимает блокировку.

Если вы хотите напечатать все числа без прерывания, вы должны заблокироватьна протяжении всего цикла for:

public void run() {
  synchronized(CommonClass.class){
    for (int i = 0; i < 10; i += 2) {
     System.out.println("Even :" + num);
    }
  }
}
1 голос
/ 28 января 2011

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

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