Программирование на языке Java


Легковесные процессы и синхронизация - часть 6


class Callme {

void call(String msg) {

System.out.println("[" + msg);

try Thread.sleep(-1000) {}

catch(Exception e) {}

System.out.println("]");

} }

class Caller implements Runnable {

String msg;

Callme target;

public Caller(Callme t, String s) {

target = t;

msg = s;

new Thread(this).start();

}

public void run() {

target.call(msg);

} }

class Synch {

public static void main(String args[]) {

Callme target = new Callme();

new Caller(target, "Hello.");

new Caller(target, "Synchronized");

new Caller(target, "World");

}

}

Вы можете видеть из приведенного ниже результата работы программы, что sleep в методе call приводит к переключению контекста между подпроцессами, так что вывод наших 3 строк-сообщений перемешивается:

[Hello.

[Synchronized

]

[World

]

]

Это происходит потому, что в нашем примере нет ничего, способного помешать разным подпроцессам вызывать одновременно один и тот же метод одного и того же объекта. Для такой ситуации есть даже специальный термин — race condition (состояние гонки), означающий, что различные подпроцессы пытаются опередить друг друга, чтобы завершить выполнение одного и того же метода. В этом примере для того, чтобы это состояние было очевидным и повторяемым, использован вызов sleep. В реальных же ситуациях это состояние, как правило, трудноуловимо, поскольку непонятно, где именно происходит переключение контекста, и этот эффект менее заметен и не всегда воспроизводятся от запуска к запуску программы. Так что если у вас есть метод (или целая группа методов), который манипулирует внутренним состоянием объекта, используемого в программе с параллельными подпроцессами, во избежание состояния гонки вам следует использовать в его заголовке ключевое слово synchronized.

Взаимодействие подпроцессов

В Java имеется элегантный механизм общения между подпроцессами, основанный на методах wait, notify и notifyAll. Эти методы реализованы, как final-методы класса Object, так что они имеются в любом Java-классе. Все эти методы должны вызываться только из синхронизованных методов. Правила использования этих методов очень просты:




- Начало -  - Назад -  - Вперед -