我有一些这样的代码:
public class HelloWorld {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
Runnable a = new Runnable(){
public void run(){
System.out.println(Thread.currentThread().getId());
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);
}
}
};
(new Thread(a)).start();
synchronized(b){
System.out.println(Thread.currentThread().getId());
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
线程B类:
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
System.out.println("Total is: " + total);
notify();
}
}
}
基本上,我有两个线程锁定 Threadb 对象 b。当我运行代码时,我看到:
1
Waiting for b to complete...
22
Waiting for b to complete...
这里的数字是线程 ID,很明显,它们是不同的线程。 而且,他们锁定的对象是相同的(b)。但是,两者都能够进入同步块(synchronized block)并等待对象。
这怎么可能?
此外,如果我在 threadB.run() 方法中插入另外 2 行:
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
System.out.println("Total is: " + total);
notify();
}
}
}
两个线程运行完成:
Total is: 4950
22
1
Waiting for b to complete...
Waiting for b to complete...
Total is: 4950
Total is: 4950
似乎在 ThreadB.run() 的旧定义中,等待线程错过了通知信号,因此它们无限期地等待。正确吗?
此外,如果线程退出时未调用notify(),锁会本质上释放(相当于notifyAll())。是这样吗?
最佳答案
因为调用Object.wait()
会释放锁。来自 the documentation :
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
似乎在 ThreadB.run() 的旧定义中,等待线程错过了通知信号,因此它们无限期地等待。这是正确的吗?它们
wait()
直到它们被notify()
(这可能是虚假的)或被中断。此外,如果线程在未调用notify() 的情况下退出,则锁会本质上释放(相当于notifyAll())。是这样吗?一旦线程
wait()
ing,锁就已经被释放。
关于java - 两个线程如何进入两个持有同一对象锁的同步块(synchronized block),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38623010/