Java 受保护的块--notifyAll()与interrupt()的比较

Java 受保护的块--notifyAll()与interrupt()的比较,java,multithreading,concurrency,synchronization,locking,Java,Multithreading,Concurrency,Synchronization,Locking,本Q寻求以下验证和/或评论/意见: 有关的示例如下: public synchronized void guardedJoy() { // This guard only loops once for each special event, which may not // be the event we're waiting for. while(!joy) { try { wait(); } catch (Int

本Q寻求以下验证和/或评论/意见:

有关的示例如下:

public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}
此代码的另一端——正确设置的
joy
如下所示:

public void setJoy2(TheClass t) {
    synchronized (t) {
        t.joy = true; 
        t.notifyAll();
    }
}
上述操作通过使用
notify()
对joy发出“信号”

另一种方法是通过
中断()
管理此“信号”:

设置
joy
并让线程等待它的是:

public void setJoy2(TheClass t) {
    t.joy = true; 
    t.interrupt(); 
}
我想比较一下这两个--
setJoy()
setJoy2()

首先,上面的
guardedJoy2()
可以正确地“听到”和
setJoy2()
——可以看到何时设置了
joy
,并按照预期的方式行事(?)
guardedJoy2()
guardedJoy()相比如何?
它的作用与
guardedJoy()
相同——我可能遗漏了一些东西,但我看不出结果有什么不同。唯一的区别是
guardedJoy2()
从循环中释放了
this
的锁,其他人在方法终止之前获取它,以获得一些意外的结果。撇开这一点不谈(即,假设这是代码中出现
joy
及其副作用的唯一地方,
guardedJoy()
guardedJoy2()
(?)

guaredjoy2()
响应
setJoy()
setJoy2()
。 它可以“听到”来自
setJoy()
当它完成时,重新获取它的锁并从那里开始。 而且,它可以“听到”来自
setJoy2()
——通过接收中断,从而抛出
InterruptedException
,以摆脱
wait()
,这也是同步语句的结束,检查
中是否设置了
joy
的条件。如果中断来自“其他人”,而不是来自一个设置
joy
,则以相同的方式再次进入循环,直到设置
joy

当调用时,
wait()
,从而在
guardedJoy2()
中释放该
的锁,
其他一些线程可以通过获取此锁进入,并执行在设置了
joy
并且
guardedJoy2()
应该正确返回之前不应该执行的操作。但是,将此放在一边(再次假设这不是问题——唯一要查找的是在控制台上的
guardedJoy2()
的最后一行上看到该消息)
在对象获得
joy
设置并从那里开始运行时,可以在对象上执行其他操作的情况下更可取(在
setJoy2()
中,线程设置
joy
不必具有对象的锁来中断它,而
setJoy()
应该具有调用
notifyAll()的锁)
在上面)

与上面的
guardeJoy2()
&
setJoy2()
相比,
guardeJoy2()
&
setJoy()
如何


蒂亚

我不认为您在第一次
setJoy
中的意思是
notify()
,而不是
notifyAll()。

首先,需要注意的是,如果在类
类型的表达式上调用
interrupt()
,则类
线程
的子类。这涉及到许多状态,您应该使用
Runnable
实例来封装要在线程上运行的逻辑,而不是对类
thread
进行子类化。报告还指出

建议应用程序不要在
线程
实例上使用
等待
通知
通知所有

这是因为一些Java实现在幕后使用这些方法来处理线程逻辑。如果您不知道该实现逻辑,并且将这些方法用于
Thread
实例,则可能会出现不希望出现的行为

然后,这可能会保证进行一些分析,抛出(创建)异常是一种,可能比这更重要。此外,异常应该用于异常情况,而不是指导应用程序逻辑

我想说的是,第二个示例的同步顺序可能不正确(假设
joy
不是
volatile
),因为
guardedJoy2
循环中的读取可能看不到写入
setJoy2
。但是,Java语言规范指出

如果线程T1中断线程T2,则中断时间为T1 与任何其他线程(包括T2)所在的任何点同步 确定T2已被中断(通过
InterruptedException
抛出或调用
线程。interrupted
线程。已中断

因此,您仍然有可见性保证

public void setJoy2(TheClass t) {
    t.joy = true; 
    t.interrupt(); 
}