首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从SCJP 6书籍中了解多线程

从SCJP 6书籍中了解多线程
EN

Stack Overflow用户
提问于 2013-03-29 19:00:43
回答 2查看 454关注 0票数 3

SCJP6手册中提供了以下代码

代码语言:javascript
运行
复制
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();
         }
     }
 }

前面的代码会不会导致死锁,因为线程a和b都在b上有一个锁(在各自的同步块中)?

我遗漏了一些东西,但不太确定是什么。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-29 19:05:09

那得看情况。

来自wait方法的文档-

会导致当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,这个方法的行为就像它简单地执行调用等待(0)一样。

当前线程必须拥有此对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象的监视器的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。

所以,如果你考虑两种情况-

  • 如果ThreadA首先获得对象b上的锁,它将等待,从而导致锁被释放,这将导致ThreadB继续其工作。
  • 如果ThreadB首先获得锁,那么它将继续其工作,释放锁,然后ThreadA将启动。接下来,ThreadA将等待对象锁b,这可能导致它永远等待。
票数 4
EN

Stack Overflow用户

发布于 2013-03-29 19:05:17

最有可能的执行如下:

  • b.start()和正在执行的run方法之间有一个轻微的延迟
  • 主线程因此设法获取b上的锁并进入synchronized

<代码>H19,然后等待<代码>D10(<代码>E111开始执行<代码>D15),监视器可用(或将很快可用),因此它可以进入<代码>D16块<代码>H217<代码>H118完成后,它通知D19可以停止等待<代码>H220<代码>H121主线程完成。<代码>H222<代码>F223

但是,根据线程调度的不同,不可能先执行run,在这种情况下,主线程可能会在b.wait()上永远等待。例如,如果你通过在b.start()后面插入一个小的Thread.sleep(100)来帮助解决这种情况,你应该观察这种行为。

底线:这是一个臭气熏天的代码,可能会遇到活跃性问题(它本身不是死锁,因为锁是可用的)。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15701930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档