java - 两个线程如何进入两个持有同一对象锁的同步块(synchronized block)

标签 java multithreading synchronized

我有一些这样的代码:

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.

  1. 似乎在 ThreadB.run() 的旧定义中,等待线程错过了通知信号,因此它们无限期地等待。这是正确的吗?它们wait()直到它们被notify()(这可能是虚假的)或被中断。

  2. 此外,如果线程在未调用notify() 的情况下退出,则锁会本质上释放(相当于notifyAll())。是这样吗?一旦线程wait()ing,锁就已经被释放。

关于java - 两个线程如何进入两个持有同一对象锁的同步块(synchronized block),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38623010/

相关文章:

java - 从数组适配器更新 ListView

java - 如何消除索引越界异常的错误

java - log4j2 配置中的用户 JVM 参数

c# - 在 C# 应用程序中使用多线程时出现 OutOfMemory 异常

java - 维护单个执行程序服务并适当关闭它

c# - for 循环问题中的 System.Threading.Tasks

java - 在 JUnit 中测试没有 sleep 的潜在死锁

java - Hibernate:通过一个查询删除所有 child

java - 寻求资源异步重建的建议/批评

java - Java中同步关键字的使用