java和同步

我正在准备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(); } } } 

在第6行,我已经读过在main中运行的线程需要锁定’b’。 为什么需要锁定此对象?

因为这就是那条线所做的。 它获得了该资源。 其他线程可以获得其他同步块,但没有其他线程可以获取该对象的锁定。

它看起来不像是通知任何特定的线程。

这是真的。 程序不知道将通知哪个线程,或者即使通知任何线程。 您作为开发人员可能会得出结论,有一个特定的线程将被通知,也许是因为它是唯一的线程wait()ing。

两个线程在这里同步Object ,即bmain()首先获取锁,但随后调用b.wait() ,它释放锁并等待某人在b上调用notify()

这意味着当run()方法(在本例中是在b调用notify()调用notify() ,这将再次唤醒main()方法。

因此, b上获取的锁在这里并不重要,重要的是两个线程都获取相同的锁,否则wait()/notify()合作将不起作用。

这是一个非常极端的案例,你会这样做。
会发生什么是main线程在ThreadB对象上同步并wait
ThreadB完成时,会引发notify ,因此main被唤醒并继续。
但这不是您通常编写的代码,即使用Thread对象进行synchronization
要查看这是怎样的情况,只需从ThreadB的循环中删除notify
由于您在Thread对象上进行同步,并且实现在Thread完成后引发通知,因此代码仍然有效。
这种行为是违反直觉的,容易出错。

代码使用wait()机制来确保result由其他ThreadB计算。

要等待对象,您需要获取该对象的锁定,该对象是line 6synchronized (b)进入图片的位置。

执行相同程序的更好方法是使用Thread#join()方法。

 public final void join() throws InterruptedException Waits for this thread to die.