之前找工作时,面试写了个生产者消费者,其中用到了wait
notify
。写完面试官问我你知道notify会产生死锁么?
我当时根本没明白,就一把锁怎么能产生死锁? 最后实际上的意思是所有的线程会进入锁的wait set
等待池。
jstack看到的效果如下
代码如下:
package com.huo.learn.thread.pc;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class NotifyHang {
private static final Object lock = new Object();
private static int count = 0;
private static final int MAX = 1;
private static void produce() {
synchronized (lock) {
while (count == MAX) {
try {
log.info(Thread.currentThread().getName() + " wait");
lock.wait();
log.info(Thread.currentThread().getName() + " wake up");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
log.info(Thread.currentThread().getName() + " produce");
lock.notify();
}
}
private static void consume() {
synchronized (lock) {
while (count == 0) {
try {
log.info(Thread.currentThread().getName() + " wait");
lock.wait();
log.info(Thread.currentThread().getName() + " wake up");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
log.info(Thread.currentThread().getName() + " consume");
lock.notify();
}
}
public static void main(String[] args) {
new Thread(() -> {
while (true) {
produce();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "生产者1").start();
new Thread(() -> {
while (true) {
produce();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "生产者2").start();
new Thread(() -> {
while (true) {
consume();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "消费者1").start();
new Thread(() -> {
while (true) {
consume();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "消费者2").start();
}
}