[英]java and synchronization
我正在为SCJP考试做准备,但是在完全了解同步方面遇到了麻烦。 在第6行,我读到main中运行的线程需要锁定'b'。 为什么需要对此对象进行锁定? 我的理解是,同步的代码块是一个受保护的区域,任何时间只能有一个线程进入? 继续前进,main中的线程释放此锁定,并等待'b中的线程完成其run方法。 然后,“ b”中的线程将通知main中的线程已完成。 但是,它看起来并不像在这里通知任何特定线程。 此示例来自Sierra and 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();
}
}
}
这两个线程在同一个Object
上同步,即b
。 main()
首先获取锁,然后调用b.wait()
,后者释放锁并等待有人在b
上调用notify()
。
这意味着当在本例中在b
调用的run()
方法调用notify()
,这将再次唤醒main()
方法。
因此,在b
上获得锁并不真正重要,重要的是两个线程都获得相同的锁,否则wait()/notify()
合作将无法正常进行。
在第6行,我读到main中运行的线程需要锁定'b'。 为什么需要对此对象进行锁定?
因为那是那条线所做的。 它获取该资源。 其他线程可以获取其他同步块,但是没有其他线程可以获取该对象的锁。
它似乎没有在这里通知任何特定的线程。
这是真的。 该程序不知道将通知哪个线程,甚至不通知任何线程。 作为开发人员,您可能会得出结论,有一个特定的线程将被通知,这也许是因为它是唯一的线程wait()ing。
这是一个非常极端的情况,您不会这样做。
发生的是main
线程在ThreadB
对象上同步并wait
。
当ThreadB
完成时,将引发一个notify
,结果main
被唤醒并继续。
但这不是您通常会编写的代码,即使用Thread
对象进行synchronization
。
要查看情况如何,只需从ThreadB
循环中删除notify
。
由于您在Thread
对象上进行了同步,因此该代码仍然可以使用,并且在Thread
完成后,该实现会引发一个通知。
该行为是违反直觉的并且容易出错。
该代码利用wait()
机制来确保result
由其他ThreadB
计算。
要等待对象,您需要获取该对象的锁定,该对象位于line 6
,其中已synchronized (b)
进入图片。
执行相同程序的更好方法是使用Thread#join()方法。
public final void join()
throws InterruptedException
Waits for this thread to die.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.