Программирование на JAVA
Меню :
Стартовая
Основы программирования
Программирование на JAVA
Программирование на C++
Программирование на Pascal
Задачи по программированию
public static void main(String s[]) {
// Создаем два потока, которые будут // конкурировать за доступ к объектам one и two Thread t1 = new Thread() { public void run() {
// Блокировка первого объекта synchronized(one) { Thread. yield();
// Блокировка второго объекта synchronized (two) {
System, out. printlnf'Success!");
}
}
}
};
Thread t2 = new Thread() { public void run() {
// Блокировка второго объекта synchronized(two) { Thread.yield();
// Блокировка первого объекта synchronized (one) {
System, out. println("Success!");
}
}
}
};
// Запускаем потоки t1 .startO; t2.start();
}
}
Если запустить такую программу, то она никогда не закончит свою работу. Обратите внимание на вызовы метода yield() в каждом потоке. Они гарантируют, что когда один поток выполнил первую блокировку и переходит к следующей, второй поток находится в таком же состоянии. Очевидно, что в результате оба потока "замрут", не смогут продолжить свое выполнение. Первый поток будет ждать освобождения второго объекта, и наоборот. Именно такая ситуация называется "мертвой блокировкой", или deadlock. Если один из потоков успел бы заблокировать оба объекта, то программа успешно бы выполнилась до конца. Однако многопоточная архитектура не дает никаких гарантий, как именно потоки будут выполняться друг относительно друга. Задержки (которые в примере моделируются вызовами yield()) могут возникать из логики программы (необходимость произвести вычисления), действий пользователя (не сразу нажал кнопку "ОК."), занятости ОС (из-за нехватки физической оперативной памяти пришлось воспользоваться виртуальной), значений приоритетов потоков и так далее.
В Java нет никаких средств распознавания или предотвращения ситуаций deadlock. Также нет способа перед вызовом синхронизированного Метода узнать, заблокирован ли уже объект другим потоком. Программист сам должен строить работу программы таким образом, чтобы неразрешимые блокировки не возникали. Например, в рассмотренном примере Достаточно было организовать блокировки объектов в одном порядке (все-^ сначала первый, затем второй) - и программа всегда выполнялась бы Успешно.
Опасность возникновения взаимных блокировок заставляет с осо-\ нНым вниманием относиться к работе с потоками. Например, важно п°мнить, что если у объекта потока был вызван метод sleep(