我正在准备SCJP考试,我在完全理解同步方面遇到了麻烦。在第6行,我已经读过在main中运行的线程需要锁定'b'。为什么需要锁定此对象?我的理解是同步的代码块是一个受保护的区域,任何时候只有一个线程可以进入?继续,main中的线程释放此锁并等待'b中的线程完成其run方法。然后'b'中的线程用于通知main中的线程已完成。但是,它看起来并不像是通知任何特定的线程。这个例子来自Sierra和Bates SCJP的书。任何可以在这上面散发的光都会受到赞赏。感谢
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
**synchronized(b) { //line 6**
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
}
class ThreadB extends Thread {
int total;
public void run() {
System.out.println("K");
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
notify();
}
}
}
答案 0 :(得分:2)
这两个线程在这里Object
同步,即b
。 main()
首先获取锁定,然后调用b.wait()
,这会释放锁定并等待某人在notify()
上呼叫b
。
这意味着当run()
方法(在本案例中调用b
时)调用notify()
时,这将再次唤醒main()
方法。
因此,b
上获取的锁在这里并不重要,重要的是两个线程都获取相同的锁,否则wait()/notify()
合作将无效。
答案 1 :(得分:2)
在第6行,我已经读过在main中运行的线程需要锁定'b'。为什么需要锁定此对象?
因为这就是那条线的作用。它获得了该资源。其他线程可以获得其他同步块,但没有其他线程可以获取该对象的锁定。
它看起来不像是通知任何特定的线程。
这是事实。程序不知道哪个线程将被通知,或者即使任何线程将被通知。您作为开发人员可能会得出结论,有一个特定的线程将被通知,也许是因为它是唯一的线程wait()ing。
答案 2 :(得分:2)
这是一个非常极端的案例,你会不这样做
会发生什么是main
线程在ThreadB
对象和wait
上同步
当ThreadB
完成后,会引发notify
,结果main
被唤醒并继续。
但这不是您通常编写的代码,即Thread
使用synchronization
个对象
要查看此案例如何,只需从notify
的循环中删除ThreadB
由于您在Thread
对象上进行同步,并且实现在Thread
完成后引发通知,因此代码仍然有效。
这种行为是违反直觉的,容易出错。
答案 3 :(得分:0)
代码使用wait()
机制来确保result
由其他ThreadB
计算。
要等待对象,您需要获取line 6
,synchronized (b)
进入图片的对象的锁定。
执行相同程序的更好方法是使用Thread#join()方法。
public final void join()
throws InterruptedException
Waits for this thread to die.