当前位置: 首页 > 知识库问答 >
问题:

Java同步正在退出时自动通知?这是预期的吗?

谢诚
2023-03-14

Java问题:

自动退出同步块不会notifyAll()。这是预期的行为吗?

我已经测试过了,它似乎是 1。当执行脱离同步块时,它会自动通知All() 2。当方法本身被同步时,它会在返回时自动通知()。( 不通知全部() )

代码:

public class Test {

    public static void main(String[] args) throws InterruptedException {

        MyThread lock = new MyThread();

        new WatingThread(lock,1).start();
        new WatingThread(lock,2).start();

        //above tow threads would start and then wait for a lock 


        lock.start();

    }
}

class MyThread extends Thread {

    public void run() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("MyThread is trying to acquire the lock ..");
        synchronized (this) {
            System.out.println("MyThread has acquired the lock !!");

            System.out.println("MyThread is Coming out of synch block..");
        }
        System.out.println("MyThread has released the lock !!");

    }
}


class WatingThread extends Thread
{
    private Object lock;
    private int id;

    public WatingThread(Object lock, int id )
    {
        this.lock = lock;
        this.id = id;
    }

    @Override
    public void run() {
        System.out.println(String.format("[%d] : Check if lock is available ...",new Object[]{id}));
        synchronized (lock) {
            System.out.println(String.format("[%d] : Acquired the lock !!",new Object[]{id}));
            try {
                System.out.println(String.format("[%d] : Going to wait on lock.. ",new Object[]{id}));
                lock.wait();
                System.out.println(String.format("[%d] : Got notified !!!",new Object[]{id}));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(String.format("[%d] :I am done !!",new Object[]{id}));
        }
    }


}

输出:

[2] :检查锁是否可用…
[2]:获得了锁
[1]:检查锁是否可用…
[2]:正在等待锁…
1]:获得了锁
[1]:正在等待锁定。
MyThread正在尝试获取锁定。
MyThread已获取锁定
MyThread正在脱离同步块..
MyThread已释放锁定
[1]:收到通知
[1]:我完了
[2]:收到通知
[2]:我完了!!

共有2个答案

缑修齐
2023-03-14

不应将 Thread 对象用作锁定对象。查看更多有问题的解释 java 是否隐式通知等待线程?。

广告:乔恩·斯基特(Jon Skeet)在那里发表演讲:)(这是上述链接问题中答案的直接链接。

还有一个从注释中链接的问题,现在我将使它更容易实现:当调用thread.join()时,谁以及何时通知thread.wait()?

壤驷高旻
2023-03-14

您所发现的是,java.lang.Thread在内部使用等待工具,将其本身用作锁。这在线程的描述中有记录。join()方法(可能不是最好的地方):

该实现使用了一个循环的< code>this.wait调用,条件是< code>this.isAlive。当线程终止时,调用< code>this.notifyAll方法。建议应用程序不要对线程实例使用< code>wait 、< code>notify或< code>notifyAll。

顺便说一句,如果您使用while循环来检查等待的条件是否按照最佳实践的要求发生了变化,这将防止这种唤醒,当然,最好是只使用< code>Object作为锁。

 类似资料:
  • 编辑:如果不是线程安全的,我正在寻找一个关于竞争条件的描述,这样我就可以更好地理解潜在的问题并填补知识空白。

  • 在支付完成后,从支付宝服务器请求我们的异步通知地址,这个才应该是做支付成功处理的时机。 // SDK实例化,传入公共配置 $sdk = new \Yurun\PaySDK\AlipayCrossBorder\SDK($params); class PayNotify extends \Yurun\PaySDK\AlipayCrossBorder\Online\Notify\Pay { /

  • 问题内容: 下面是一个简单的Java程序。它具有一个称为“ cnt”的计数器,该计数器递增,然后添加到名为“ monitor”的列表中。“ cnt”由多个线程递增,并且值由多个线程添加到“ monitor”。 在方法“ go()”的末尾,cnt和monitor.size()应该具有相同的值,但它们没有相同的值。monitor.size()确实具有正确的值。 如果通过取消注释已注释的同步块之一并注释

  • 退款后会发送通知。 官方文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=9 // SDK实例化,传入公共配置 $sdk = new \Yurun\PaySDK\Weixin\SDK($params); class RefundNotify extends \Yurun\PaySDK\Weixin\No

  • 您可以通过 Bluetooth 连接,以无线方式,将数据从手表传输至 Polar Flow 应用程式。或者您可以使用 USB 端口和 FlowSync 软件,将手表与 Polar Flow 网络服务同步。若要在手表与 Flow 应用程式之间同步数据,您需要拥有 Polar 账户。如果您想将手表上的数据直接同步到网络服务,除了 Polar 账户,您还需要 FlowSync 软件。如果您已设置手表,已

  • 您可以通过 Bluetooth 连接,以无线方式,将数据从手表传输至 Polar Flow 应用程式。或者您可以使用 USB 端口和 FlowSync 软件,将手表与 Polar Flow 网络服务同步。若要在手表与 Flow 应用程式之间同步数据,您需要拥有 Polar 账户。如果您想将手表上的数据直接同步到网络服务,除了 Polar 账户,您还需要 FlowSync 软件。如果您已设置手表,已