Java 受保护的块--notifyAll()与interrupt()的比较
本Q寻求以下验证和/或评论/意见: 有关的示例如下: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
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();
}