一些findbugs告警解决

文章讲述了在Java多线程编程中,使用wait和notify进行线程同步时需要注意的问题,如wait需在循环中,notify需确保资源准备就绪。线程可能因虚假唤醒而需要条件变量控制,正确的模式是结合条件判断和同步块来防止错误。给出了Producer-Consumer问题的例子以及如何避免WA_NOT_IN_LOOP,NAKED_NOTIFY和UNCOND_WAIT告警。
摘要由CSDN通过智能技术生成

WA_NOT_IN_LOOP/NAKED_NOTIFY/UNCOND_WAIT

这几个告警涉及到wait和notify的使用方法,网上文章语焉不详的,这里记录一下怎么处理。

WA_NOT_IN_LOOP:wait要在loop循环里。
NAKED_NOTIFY:notify/notifyAll调用之前要把资源准备好、把状态设置好,不能只调notify/notifyAll本身。
UNCOND_WAIT:跟WA_NOT_IN_LOOP其实是一个问题,wait要在loop循环里,且有一个条件变量控制

主要根因是,线程有可能被虚假的唤醒(spurious notify),这时需要一个条件变量确保其再次陷入等待。

摘了SO上的一段描述:

The problem is that you're trying to use wait and notify in ways that they are not designed to be used. Usually, wait and notify are used to have one thread wait until some condition is true, and then to have another thread signal that the condition may have become true. For example, they're often used as follows:

/* Producer */
synchronized (obj) {
    /* Make resource available. 这里要有条件变量设置的代码 */
    obj.notify();
}

/* Consumer */
synchronized (obj) {
    while (/* resource not available 这里要有条件变量就绪的判断,规避虚假唤醒问题 */) {
        obj.wait();
    }    

    /* Consume the resource. */
}
The reason that the above code works is that it doesn't matter which thread runs first. If the producer thread creates a resource and no one is waiting on obj, then when the consumer runs it will enter the while loop, notice that the resource has been produced, and then skip the call to wait. It can then consume the resource. If, on the other hand, the consumer runs first, it will notice in the while loop that the resource is not yet available and will wait for some other object to notify it. The other thread can then run, produce the resource, and notify the consumer thread that the resource is available. Once the original thread is awoken, it will notice that the condition of the loop is no longer true and will consume the resource.

More generally, Java suggests that you always call wait in a loop because of spurious notifications in which a thread can wake up from a call to wait without ever being notified of anything. Using the above pattern can prevent this.

总结起来,要将条件变量的设置+notify一起用synchronized包起来,将条件变量的while判断+wait一起用synchronized包起来,才能做到正确的使用wait/notify。
下面是一段常见的伪码样例:

@PreDestroy
public void fini() {
    synchronized (this) {
        this.isStopped = true;
        this.notifyAll();
    }
}

public void trigger(Event event) {
    synchronized (this) {
        this.isInProgress = event.hasSomeFlag();

        if (!this.isInProgress) {
            this.notifyAll();
        }
    }
}

public void wait4Sth() {
    synchronized (this) {
        while (this.isInProgress && !isStopped) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                log.warn("wait4Sth interrupted, cause:{}", e.toString());
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值