死锁
public class Main {
static class Counter {
final Object o1 = new Object();
final Object o2 = new Object();
public void increment() {
synchronized (o1) {
System.out.println("inc-o1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
synchronized (o2) {
System.out.println("inc-o2");
}
}
}
public void decrement() {
synchronized (o2) {
System.out.println("dec-o2");
synchronized (o1) {
System.out.println("dec-o1");
}
}
}
}
public static void main(String[] args) {
final Counter counter = new Counter();
final Thread thread = new Thread(counter::increment, "线程1:");
thread.start();
new Thread(counter::decrement, "线程2:").start();
//thread.interrupt();
}
}
如果有两个个生产者和一个消费者,缓冲区为最大为1,消费者先阻塞,notify 通知生产者1,生产者1生产1,然后阻塞,notify 生产者2,生产者2也阻塞,这时已经没有线程可以执行 notify,因此全部在等待无法被唤醒,产生死锁。
避免死锁要注意加锁的顺序要一致;使用 notifyAll()
而不是 notify()
去唤醒阻塞的线程。
饥饿
饥饿的产生是由于贪婪线程长时间不释放锁,导致其它需要获取锁的线程经常被阻塞。
活锁
一个线程通常会响应另一个线程的操作而行动,如果另一个线程的动作也是对这个线程的动作的响应,则可能会导致活锁。就比如两个人迎面走来,一个往左一个往右,互相谦让,一个往右一个往左。这两个线程都没有阻塞,只是忙于彼此的响应而无法恢复工作。