Java Примеры - Тупик и решение
Тупик ситуация: множество нитей заблокированы, один или все из них ждет ресурса, который будет выпущен. Так как поток блокируется на неопределенное время, поэтому программа не может быть прекращено в обычном режиме.
Четыре необходимые условия Java Deadlock:
- 1, специальный, то есть, когда ресурс представляет собой нить (владение), другие потоки не могут быть использованы
- 2, не может захватить ЗР не может быть вынужден захватить ресурсы из рук обладание ресурсами, ресурсами, ресурсы могут быть освобождены только по инициативе жильцов.
- 3, запросы, и утверждая, что, когда ресурс запрашивающий при запросе дополнительных ресурсов для поддержания владения оригинального ресурса.
- 4, ждать цикла, т.е. существует очередь: P1 P2 занимает ресурсы, P2 и P3 владение ресурсами было отмечено, П1 П3 долю ресурсов. Таким образом, образуя петлю ожидания.
Когда эти четыре условия выполнены, то тупиковый. Конечно, если дело в тупик, чтобы разорвать любого из этих условий, вы можете позволить тупиковой исчезнуть. Используйте следующий код для имитации того, что Java тупиковой продуктов.
Решение проблемы взаимоблокировки: одна синхронизируется, заключается в использовании явных блокировок для блокировки.
Если неправильное использование замков, и на экране в то же самое время, когда вы хотите заблокировать несколько объектов, будет тупиковая ситуация, следующим образом:
/* author by w3cschool.cc LockTest.java */ import java.util.Date; public class LockTest { public static String obj1 = "obj1"; public static String obj2 = "obj2"; public static void main(String[] args) { LockA la = new LockA(); new Thread(la).start(); LockB lb = new LockB(); new Thread(lb).start(); } } class LockA implements Runnable{ public void run() { try { System.out.println(new Date().toString() + " LockA 开始执行"); while(true){ synchronized (LockTest.obj1) { System.out.println(new Date().toString() + " LockA 锁住 obj1"); Thread.sleep(3000); // 此处等待是给B能锁住机会 synchronized (LockTest.obj2) { System.out.println(new Date().toString() + " LockA 锁住 obj2"); Thread.sleep(60 * 1000); // 为测试,占用了就不放 } } } } catch (Exception e) { e.printStackTrace(); } } } class LockB implements Runnable{ public void run() { try { System.out.println(new Date().toString() + " LockB 开始执行"); while(true){ synchronized (LockTest.obj2) { System.out.println(new Date().toString() + " LockB 锁住 obj2"); Thread.sleep(3000); // 此处等待是给A能锁住机会 synchronized (LockTest.obj1) { System.out.println(new Date().toString() + " LockB 锁住 obj1"); Thread.sleep(60 * 1000); // 为测试,占用了就不放 } } } } catch (Exception e) { e.printStackTrace(); } } }
Приведенный выше код выполняется выход:
Tue May 05 10:51:06 CST 2015 LockB 开始执行 Tue May 05 10:51:06 CST 2015 LockA 开始执行 Tue May 05 10:51:06 CST 2015 LockB 锁住 obj2 Tue May 05 10:51:06 CST 2015 LockA 锁住 obj1
В этот тупик.
Чтобы решить эту проблему, мы не используем, чтобы отобразить замки, мы используем семафоры для управления.
Семафор может контролировать, сколько потоков могут получить доступ к ресурсам, мы указываем здесь может быть только один доступ потоков, то сделать подобную блокировку. Семафор можно указать тайм-аут, чтобы получить, мы можем в соответствии с тайм-аут, сделайте дополнительную обработку.
Дело не может получить, вообще повторить попытку, или указать количество попыток, вы можете выйти немедленно.
Посмотрите на следующий код:
/* author by w3cschool.cc UnLockTest.java */ import java.util.Date; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class UnLockTest { public static String obj1 = "obj1"; public static final Semaphore a1 = new Semaphore(1); public static String obj2 = "obj2"; public static final Semaphore a2 = new Semaphore(1); public static void main(String[] args) { LockAa la = new LockAa(); new Thread(la).start(); LockBb lb = new LockBb(); new Thread(lb).start(); } } class LockAa implements Runnable { public void run() { try { System.out.println(new Date().toString() + " LockA 开始执行"); while (true) { if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockA 锁住 obj1"); if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockA 锁住 obj2"); Thread.sleep(60 * 1000); // do something }else{ System.out.println(new Date().toString() + "LockA 锁 obj2 失败"); } }else{ System.out.println(new Date().toString() + "LockA 锁 obj1 失败"); } UnLockTest.a1.release(); // 释放 UnLockTest.a2.release(); Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的 } } catch (Exception e) { e.printStackTrace(); } } } class LockBb implements Runnable { public void run() { try { System.out.println(new Date().toString() + " LockB 开始执行"); while (true) { if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockB 锁住 obj2"); if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockB 锁住 obj1"); Thread.sleep(60 * 1000); // do something }else{ System.out.println(new Date().toString() + "LockB 锁 obj1 失败"); } }else{ System.out.println(new Date().toString() + "LockB 锁 obj2 失败"); } UnLockTest.a1.release(); // 释放 UnLockTest.a2.release(); Thread.sleep(10 * 1000); // 这里只是为了演示,所以tryAcquire只用1秒,而且B要给A让出能执行的时间,否则两个永远是死锁 } } catch (Exception e) { e.printStackTrace(); } } }
Примеры выше выходного кода структуры:
Tue May 05 10:59:13 CST 2015 LockA 开始执行 Tue May 05 10:59:13 CST 2015 LockB 开始执行 Tue May 05 10:59:13 CST 2015 LockB 锁住 obj2 Tue May 05 10:59:13 CST 2015 LockA 锁住 obj1 Tue May 05 10:59:14 CST 2015LockB 锁 obj1 失败 Tue May 05 10:59:14 CST 2015LockA 锁 obj2 失败 Tue May 05 10:59:15 CST 2015 LockA 锁住 obj1 Tue May 05 10:59:15 CST 2015 LockA 锁住 obj2