Синхронизация подпроцессов
Приведем простейший пример. Метод run () в листинге 17.5 выводит строку "Hello, World!" с задержкой в 1 секунду между словами. Этот метод выполняется двумя подпроцессами, работающими с одним объектом th. Программа выполняется два раза. Первый раз метод run () не синхронизирован, второй раз синхронизирован, его заголовок показан в листинге 17.4 как комментарий. Результат выполнения программы представлен на рис. 17.3.
Листинг 17.5. Синхронизация метода.
class TwoThreads4 implements Runnable{ public void run(){ // synchronized public void run(){ System.out.print("Hello, "); try{ Thread.sleep(1000); }catch(InterruptedException ie){} System.out.println("World!"); } public static void main(String[] args){ TwoThreads4 th = new TwoThreads4(); new Thread(th).start(); new Thread(th).start(); } }
Рис. 17.3. Синхронизация метода
Действия, входящие в синхронизированный блок или метод образуют критический участок (critical section) программы. Несколько подпроцессов, собирающихся выполнять критический участок, встают в очередь. Это замедляет работу программы, поэтому для быстроты ее выполнения критических участков должно быть как можно меньше, и они должны быть как можно короче.
Многие методы Java 2 SDK синхронизированы. Обратите внимание, что на рис. 17.1 слова выводятся вперемешку, но каждое слово выводится полностью. Это происходит потому, что метод print () класса Printstream синхронизирован, при его выполнении выходной поток system, out блокируется до тех пор, пока метод print () не закончит свою работу.
Итак, мы можем легко организовать последовательный доступ нескольких подпроцессов к полям одного объекта с помощью оператора synchronized () {}. Синхронизация обеспечивает взаимно исключающее (mutually exclusive) выполнение подпроцессов. Но что делать, если нужен совместный доступ нескольких подпроцессов к общим объектам? Для этого в Java существует механизм ожидания и уведомления (wait-notify).