我有一个简单的代码片:
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
结果:
Waiting for b to complete...
Total is: 4950
我有一个问题,为什么我们需要使用这个代码,我不清楚这里。
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
当我在这里使用synchronized时,我的结果相同。
答案 0 :(得分:1)
当notify()
被调用且相应的wait()
看到时,&#34;发生之前&#34}建立关系:ThreadB
之前notify()
中发生的所有事件将在相应的ThreadA
返回后在wait()
中显示。因此,在您的情况下,total
的所有修改都会在notify()
之前完成,并且可以安全地假设ThreadA
会看到这些更改。
但请注意,使用wait()
/ notify()
进行同步的方式不正确。可能存在虚假的唤醒(即wait()
在没有相应的notify()
的情况下醒来。有一些特定的惯用方法来使用这些方法(它们实际上是伪装的POSIX条件变量)。其中之一是定义一个&#34;条件&#34;可以从两个主题中检查(例如&#34; is_completed
变量为true
)并在循环中调用wait()
,请参阅here
答案 1 :(得分:0)
当线程终止时,它会调用this.notifyAll()
,因此您在notify()
中对ThreadB
的调用并非绝对必要。
但是,作为Thread.join()
注释的文档,不建议在Thread
对象上使用监视操作:
当线程终止时,将调用
this.notifyAll
方法。建议应用程序不要在wait
个实例上使用notify
,notifyAll
或Thread
。
如果您想等待ThreadB
完成,只需从b.join()
拨打ThreadA
即可。您不需要任何同步块:
public class ThreadA {
public static void main(String[] args) throws InterruptedException {
ThreadB b = new ThreadB();
b.start();
System.out.println("Waiting for b to complete...");
b.join();
System.out.println("Total is: " + b.total);
}
}
public class ThreadB extends Thread {
int total;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
total += i;
}
}
}