如何确定哪个线程获得对象的内部锁?

时间:2015-02-04 16:29:45

标签: java multithreading

 public 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){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

在上面的示例中,对象b已同步。 b在主线程输出其总值之前完成计算。 输出:

Waiting for b to complete...
Total is: 4950

如果main线程首先获得b的锁定,则main线程将执行synchronized(b)块。请b.wait()暂停线程b(线程b还没有运行)?如果是,该代码如何产生结果?

如果线程b首先获得内在锁定,那么notify()的结果是什么?

2 个答案:

答案 0 :(得分:3)

当您使用notify / wait时,您应该根据状态更改执行此操作。如果你不这样做,你可以解决一些问题。

如果在没有线程等待时通知(),则通知将丢失。稍后等待(等待)可能会永远等待。

如果你等待(),它可以虚假地唤醒,即它并不意味着有通知。

解决方案是:

  • 不使用通知/等待,因为它在10年前被很大程度上取代了 并发库

  • 让notify()线程更改字段/状态并拥有wait()线程 在循环中检查这个。

正如James Large所说,wait()ing是不公平的,因为无法保证第一个等待的线程将被通知下一个。

此外,如果不保持相同的同步锁定并且期望它始终正常运行,则无法更改状态。

答案 1 :(得分:2)

  

b.wait()暂停线程b(线程b尚未运行)?如果是的话,如何   这段代码能产生结果吗?

不,这是synchronized(this)(其中this引用与b相同的对象)将阻止另一个线程。一旦b.wait被调用,b引用的对象上的监视器被释放,主线程进入休眠状态,另一个线程获取监视器,进入synchronized块。

  

如果线程b首先获得内部锁定,那么结果是什么   notify()

b / this没有线程等待,所以notify基本上什么都不做。当你的另一个线程释放监视器时,你的主线程将获取它并调用wait,永远等待,因为notify没有别的东西。