notify和notifyAll的区别,notify死锁问题
具体讲解参照博客 下面补充一个例子,来说明,使用notify会产生死锁,但是使用notifyAll不会。
原题为
大体意思是:四个线程,调用同一个对象的四个不同方法,然后实现线程的同步。
在这里使用了synchornized和state来实现这个题目。 下面分析一种情况说明notify会产生死锁,而notifyAll会。
修改完state = 0后,使用notify激活了应该执行state = 3的线程A。 然后,线程state = 0, 调用了wait方法,锁死了自己。 此时,锁队列上,挂了四个线程,虽然此时的锁已经释放了,但是没有外部的干预,四个线程都没有回到竞争队列上面的时候。 这就出现了有锁,但是无法执行的状态。 但是这并不是操作系统意义上面的死锁。因为不满足死锁的四个状态。
package leetcode;
import java.util.function.IntConsumer;
/*
*
* 这里是一个错误的同步
* */
public class FizzBuzz3 extends FizzBuzz{
// 使用synchornize + state的方式来实现
private int state = 0; // 0 : 数字, 1 :fizz, 2:buzz, 3
private Object obj = new Object();
private int n;
public FizzBuzz3(int n) {
super(n);
this.n = n;
}
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
for (int i = 3; i <= n; i += 3) {
if (i % 5 == 0) continue;
synchronized (obj) {
while (state != 1) {
obj.wait();
}
printFizz.run();
state = 0;
obj.notifyAll();
}
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
for (int i = 5; i <= n; i += 5) {
if (i % 3 == 0) continue; // 如果不行,就不该状态,否则最后一个可能输出不了
synchronized (obj) {
while (state != 2) {
obj.wait();
}
printBuzz.run();
state = 0;
obj.notifyAll(); // 可能会死锁,如果都wait就死锁了。
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for (int i = 15; i <= n; i += 15) {
// 只要等于3,就可以直接输出了
synchronized (obj) {
while (state != 3) {
obj.wait();
}
// System.out.println("
state = " + state + " i = " + i);
printFizzBuzz.run();
state = 0; // 只有输出才有资格改,否则自己也能竞争
obj.notifyAll();
}
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
synchronized (obj) {
while (state != 0) {
obj.wait();
}
if (i % 3 != 0 && i % 5 != 0) {
printNumber.accept(i);
} else {
if (i % 3 == 0 && i % 5 == 0) {
state = 3;
} else if (i % 5 == 0) {
state = 2;
} else state = 1;
}
// System.out.println(" state = " + state);
obj.notifyAll();
}
}
}
public static void main(String[] args) throws Exception{
String[] className = {
"leetcode.FizzBuzz3", "20"};
FuzzBuzzMain.main(className);
}
}
下一篇:
Java小游戏-俄罗斯方块
