将timlesProc(100);
置于synchronized
块内部或外部,如ThreadA中显示的注释行,是否有任何区别。
根据我的理解,没有区别,因为两个线程都处于运行模式,并且两者都可以在同一时间执行。但根据实验,当timlesProc(100);
位于synchronized
内时 - 它始终先运行,然后运行b.sync.wait();
并且不会'永远等待'问题。当timlesProc(100);
在synchronized
之外时 - 我总是'永远等待'。为什么会这样,或者我的理解不正确?
class ThreadA {
public static void timlesProc(int count)
{
for(int i=0;i<count;i++)
{
System.out.println(Thread.currentThread().getName()+" "+ Integer.toString(i));
}
}
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
//timlesProc(100);
synchronized(b.sync)
{
timlesProc(100);
try
{
System.out.println("Waiting for b to complete...");
b.sync.wait();
System.out.println("waiting done");
} catch (InterruptedException e) {}
}
}
}
class ThreadB extends Thread {
Integer sync = new Integer(1);
public void run() {
synchronized(sync)
{
sync.notify();
System.out.println("notify done");
}
}
}
答案 0 :(得分:4)
你有竞争条件。如果timlesProc
方法超出synchronized
,则非常可能您将进行上下文切换,而另一个Thread
将能够执行获取锁定并通知main
线程(即使它没有等待)。然后当你到达 p>
b.sync.wait();
你永远等待,因为notify()
没有留下任何东西。
如果您将timlesProc
放在synchronized
内,则会转到wait()
,然后会收到通知。然后程序结束。
请参阅Cruncher's answer了解程序永远等待的另一种可能性。
答案 1 :(得分:2)
实际上,即使timlesProc
调用在同步块内,仍然存在竞争条件,不太可能发生。
如果b.start()
发生,并且它在主线程之前获取同步锁定,那么它仍将首先通知导致Sotirios Delimanolis在其answer中提到的相同问题。