Вывод кода синхронизации в неправильном порядке в Java

59
8

В настоящее время я изучаю Java, и я достиг темы синхронизации.

По некоторым причинам приведенный ниже код (на основе кода из полного справочника JAVA - Herbert Schildt 7th Edition, стр. 239-240) не дает требуемого результата.

Код:

package package1;
class Call{
synchronized public void call(String msg){
System.out.print("[" + msg);
try{
Thread.sleep(100);
}catch (InterruptedException e){
System.out.println("Interrupted Exception Caught");
}
System.out.println("]");
}
}

class CallMe implements Runnable{
String msg;
Call target;
Thread t;

public CallMe(Call targ, String message){
target = targ;
msg = message;
t = new Thread(this);
t.start();
}

public void run(){
target.call(msg);
}
}

public class Synchronization {
public static void main(String[] args) {
Call target = new Call();
CallMe obj1 = new CallMe(target, "Hello");
CallMe obj2 = new CallMe(target, "Synchronized");
CallMe obj3 = new CallMe(target, "World");

try{
obj1.t.join();
obj2.t.join();
obj3.t.join();
}catch (InterruptedException e){
System.out.println("Interrupted Exception Caught");
}
}
}

Требуемый вывод:

[Hello]
[Synchronized]
[World]

Фактический результат (я использую Eclipse на Macbook Pro в конце 2013 года):

[Hello]
[World]
[Synchronized]

Я прочитал, что все эти темы отличаются от компьютера к компьютеру.

Может ли кто-нибудь объяснить мне, почему это не работает?

спросил(а) 2014-03-23T15:40:00+04:00 6 лет, 7 месяцев назад
1
Решение
82

Поскольку разные экземпляры CallMe вызывается параллельно, и у вас нет гарантии, в каком порядке они обрабатываются. Единственное, что вы знаете, это то, что Call.call(String) не вызывается параллельно, поскольку этот метод synchronized.

ответил(а) 2014-03-23T15:47:00+04:00 6 лет, 7 месяцев назад
41

Ответьте немного на Питера. Вся синхронизация не позволяет сумасшедшим.

Попробуйте этот код без синхронизированного вызова, и вы увидите, что класс вызова может ударить.out, поскольку он не учитывает другие объекты. Я получаю вывод вроде этого, с "синхронизированным" удаленным:

[Hello[World[Synchronized]
]
]

С синхронизированным в вас что-то вроде того, что вы видите, но это не гарантирует порядок. Иногда вы получаете:

[Hello]
[World]
[Synchronized]

Иногда вы получаете:

[Hello]
[Synchronized]
[World]

Запустите его снова и снова, и вы поймете, что я имею в виду.
Чтобы действительно выбросить его, попробуйте использовать:

Thread.sleep(1);

ответил(а) 2014-03-23T16:06:00+04:00 6 лет, 7 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема