从生产者消费者模型模拟notify死锁

生产者
public class Producer implements Runnable {
List cache;

public Producer(List<Integer> cache) {
    this.cache = cache;
}

@Override
public void run() {
    while (true) {
        produce();
    }
}

private void produce() {
    synchronized (cache) {
        try {
            while (cache.size() == 1) {
                cache.wait();
            }

            // 模拟一秒生产一条消息
            Thread.sleep(1000);
            cache.add(new Random().nextInt());

            cache.notify();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

}
消费者
public class Consumer implements Runnable {
List cache;

public Consumer(List<Integer> cache) {
    this.cache = cache;
}

@Override
public void run() {
    while (true) {
        consume();
    }
}

private void consume() {
    synchronized (cache) {
        try {
            while (cache.isEmpty()) {
                cache.wait();
            }

            System.out.println("Consumer consumed [" + cache.remove(0) + "]");
            cache.notify();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

}
运行
public class WaitNotifyTest {
public static void main(String[] args) throws Exception {
List cache = Lists.newArrayList();
new Thread(new Consumer(cache)).start();
new Thread(new Consumer(cache)).start();

    new Thread(new Producer(cache)).start();
    new Thread(new Producer(cache)).start();
}

}

先来说明两个定义:
锁池:假设线程A已经拥有了某个对象(不是类)的锁,而其他线程想要调用这个对象的Synchronize方法(或者Synchronize块),由于这些方法在进入Synchronize方法之前必须先或获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池
等待池:假设线程A调用了某个对象的wait方法,那么线程A就会释放该对象的锁,并且进入等待池中等待唤醒

好了场景模拟
生产者P1,P2
消费者C1,C1

第一回合
C1获得了对象锁,C2,P1,P2进入锁池,但是cache为0,C1进入等待池
Round2
C2获得了对象锁,P1,P2待在锁池中,C1待在等待池中,同理C2进入等待池
Round3
P1获得了对象锁,P2待在锁池中,C1,C2待在等待池中,P1生产一条消息,随机唤醒C1,随后又进入锁池
Round4
P1又获得了对象锁,P2,C1待在锁池中,C2待在等待池中,cache为1,P1进入等待池
Round5
P2获得了对象锁,C1待在锁池中,C2,P1待在等待池中,cache为1,P2进入等待池
round6
C1获得了对象锁,锁池暂空,C2,P1,P2待在等待池中,C1消费一条数据,随机唤醒C2,随后又进入了锁池
round7
C1又获得了对象锁,C2待在锁池中,P1,P2待在等待池中,cache为0,C1进入等待池
round8
C2获得了对象锁,cache为0,进入等待池,造成死锁

简洁版—>锁池用[]表示,等待池用()表示

[C1,c2,p1,p2]()->
c1;[c2,p1,p2]()->
c2;[p1,p2](c1)->
p1;[p2](c1,c2)->
p1;[p2,c1](c2)->
p2;[c1](p1,c2)->
c1;[c2](p1,p2)->
c2;[c1,p1](p2)->
c1;[p1](p2,c2)->
p1;[](p2,c2,c1)->
p2;[](c2,c1,p1)->
死锁

或者还有更快的GG

p1,[c1,c2,p2]()
p2,[c1,c2](p1)
c1,[c2](p1,p2)
c2,[p1](c1.p2)
p1,[](c1,c2,p2)
p2,[](c1,c2,p1)
—>死锁
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值