以下线程代码中的同步如何工作以及代码流是什么?

时间:2016-12-22 00:15:39

标签: java multithreading synchronization runnable

class ThreadA {
public static void main(String[] args) {
    ThreadB b = new ThreadB();
    b.start();
    synchronized (b) {
        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() {
    synchronized (this) {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
        notify();
    }
}}

我无法理解代码流以及如何在上述程序中调用run方法。 当对象属于类ThreadB时,为什么main()的{​​{1}}线程能够同步对象ThreadA。除了b主题遇到wait()时,执行情况如何转移到main()中的run()

2 个答案:

答案 0 :(得分:1)

  

为什么即使在ThreadB的run()能够执行之前,main()也会到达synchronized块。

您的程序有竞争条件

main()调用b.start()之后,有两个线程正在运行,未同步,并且它们竞争锁定(即同步)b对象。没有办法预测哪个线程会先锁定它。

如果main()线程首先锁定它,那么它将调用b.wait()。这将暂时解锁b对象,并允许其他线程运行。另一个线程将完成其工作,调用b.notify()并退出synchronized块。退出后,main()主题就可以从wait()调用返回。

如果第二个线程是第一个锁定b对象,则行为将不同:它将完成其工作,调用notify()并返回。但是notify()调用在这种情况下不会执行任何操作,因为main()线程将被阻止尝试进入synchronized块。它不会在b.wait()电话中等待,notify()如果没有其他线程在等待,则不会做任何事情。

那么接下来会发生的情况是,当ThreadB线程离开synchronized块时,main()线程将能够输入它并调用wait() 。该程序将在此时挂起,因为ThreadB线程已完成其工作并已死亡。没有其他线程可以拨打notify()

当两个(或更多)线程竞相做某事时,我们将其称为竞争条件,并且程序的输出取决于首先到达哪个。

答案 1 :(得分:0)

  

除了main()线程遇到wait()时,执行如何转换为ThreadB中的run()。

在调用wait()

之前

如果它将在下一步调用wait method,则表示主线程当前持有对象b监视器。如果threadB想要执行 run()方法,它将被阻止等待主线程所持有的b的{​​em> monitor

调用wait()

这意味着main thread发布监视器,进入等待状态,并建议线程调度程序 re_dispatch。然后 ThreadB 可以获得监视器并制作东西。

<强>通知()

完成其工作后,threadB调用 notify()来唤醒正在等待此对象的监视器的单个线程,这里是主线程主线程将继续开展工作。