死锁

  1. public class Main {
  2. static class Counter {
  3. final Object o1 = new Object();
  4. final Object o2 = new Object();
  5. public void increment() {
  6. synchronized (o1) {
  7. System.out.println("inc-o1");
  8. try {
  9. Thread.sleep(1000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. return;
  13. }
  14. synchronized (o2) {
  15. System.out.println("inc-o2");
  16. }
  17. }
  18. }
  19. public void decrement() {
  20. synchronized (o2) {
  21. System.out.println("dec-o2");
  22. synchronized (o1) {
  23. System.out.println("dec-o1");
  24. }
  25. }
  26. }
  27. }
  28. public static void main(String[] args) {
  29. final Counter counter = new Counter();
  30. final Thread thread = new Thread(counter::increment, "线程1:");
  31. thread.start();
  32. new Thread(counter::decrement, "线程2:").start();
  33. //thread.interrupt();
  34. }
  35. }
  1. 如果有两个个生产者和一个消费者,缓冲区为最大为1,消费者先阻塞,notify 通知生产者1,生产者1生产1,然后阻塞,notify 生产者2,生产者2也阻塞,这时已经没有线程可以执行 notify,因此全部在等待无法被唤醒,产生死锁。

避免死锁要注意加锁的顺序要一致;使用 notifyAll() 而不是 notify() 去唤醒阻塞的线程。

饥饿

饥饿的产生是由于贪婪线程长时间不释放锁,导致其它需要获取锁的线程经常被阻塞。

活锁

一个线程通常会响应另一个线程的操作而行动,如果另一个线程的动作也是对这个线程的动作的响应,则可能会导致活锁。就比如两个人迎面走来,一个往左一个往右,互相谦让,一个往右一个往左。这两个线程都没有阻塞,只是忙于彼此的响应而无法恢复工作。