Java多线程同步操作中为什么要用 while 而不是 if

比方说在多生产、多消费的场景

这里直接举例来说明吧

class Buf{
    private final int MAX = 5;
    private final ArrayList<Integer> list = new ArrayList<>();
    synchronized void put(int v) throws InterruptedException {
        if (list.size() == MAX) {
            wait();
        }
        System.out.println("put v = "+v + ", thread = "+ Thread.currentThread().getName());
        list.add(v);
        notifyAll();
    }

    synchronized int get() throws InterruptedException {
        // 为什么多线程同步的时候 要用while而不是if
        //A线程和B线程在执行 get 方法的时候,由于list 的 size 为 0, 所以A和B线程都执行wait方法阻塞住并且释放了锁。
        //C 线程执行put操作是,调用 notifyAll() 方法唤醒A和B线程,假设是A线程先获得锁,那么A remove 后,现在 list 的大小又为 0 了
        // 此时线程A调用 notifyAll 方法来唤醒B线程,那么B线程获得锁之后,会直接调用 remove 方法,此时 list 的大小为0,所以报 IndexOutOfBoundsException

        // 解决方法就是将 if 改为 while 就好了,因为 是while的话, 此时线程A调用 notifyAll 方法来唤醒B线程,那么B线程获得锁之后 会执行 while 语句,判断 size == 0,执行 wait 方法
        if (list.size() == 0) {
            System.out.println("get 执行 wait" + ", thread = "+ Thread.currentThread().getName());
            wait();
        }
        int v = list.remove(0);
        System.out.println("get v = " + v + ", thread = "+ Thread.currentThread().getName());
        notifyAll();
        return v;
    }
}

具体的解释见代码中的注释吧!!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值