Перевод на русский © , 2000
Java Q&A
Java использует ключевое слово synchronized и методы wait() и notify() класса java.lang.Object для синхронизации. Существуют ли другие способы, например семафоры, в Java?
Единственные механизмы синхронизации, встроенные в Java-- это мониторы (monitors) и наборы задержек (wait sets), о которых большинство программистов даже не слышало, так как они скрыты в synchronized, wait() и notify(). К счастью, Java позволяет вам реализовать все знакомые схемы синхронизации на основе мониторов и наборов задержек. В конце этой заметки мы узнаем, как написать наш собственный класс Semaphore.
Однако перед этим давайте посмотрим немного на теоретические основы. Каждый многопотоковый (multithreaded) язык программирования должен иметь механизм для синхронизации нитей. Возьмем, например, программу с нитью, которая создает объекты, и нитью, которая использует их, как в этом примере кода:
Object data = null;
public void push(Object d) { data = d; }
public Object pop() { Object d = data; data = null; return d; }
class Producer implements Runnable { public void run() { while (true) { Object o = createNewObject(); push(o); } } }
class Consumer implements Runnable { public void run() { while (true) { Object o = pop(); doSomethingWith(o); } } }
public static void main(String args[]) { (new Thread(new Producer())).start(); (new Thread(new Consumer())).start(); }
Проблема с этими примитивными классами Producer и Consumer заключается в том, что они не содержат никаких способов для взаимодействия друг с другом. Если одна нить работает быстрее, чем другая, она должна периодически ждать, пока медленная нить сделает свою работу. Мы можем изменить методы push() и pop() так, чтобы они работали поочередно и не обгоняли друг-друга.
public void push(Object d) { while (data != null) { /* Пустой цикл задержки. */ } data = d; }
public Object pop() { while (data == null) { /* Пусто. */ } Object d = data; data = null; /* Выход из цикла для push().*/ return d; }