【问题标题】:OCJP Dumps ThreadOCJP 转储线程
【发布时间】:2015-10-20 01:14:57
【问题描述】:

谁能帮我解决以下问题?

public class Starter extends Thread{
   private int x=2;
   public static void main(String[] args) throws Exception{
      new Starter().makeItSo();
   }
   public Starter(){
      x=5;
      start(); 
   }
   public void makeItSo() throws Exception {
      join();
      x=x-1;
      System.out.println(x);
   }
   public void run(){x*=2;}
}

A. 4

B. 5

C. 8

D. 9

E.编译失败

F。运行时抛出异常

G.无法确定

在转储中,答案是 D。我知道在 new Starter().makeItSo 中创建了一个新线程。但是谁能告诉我为什么 run() 中的 x*=2 在方法 makeItSo 中的 x=x-1 和 System.out.println(x) 之间执行?

【问题讨论】:

  • 答案 D 是什么?为什么你认为任何东西都在其他东西之间执行?

标签: java multithreading scjp java-threads


【解决方案1】:

但是谁能告诉我为什么 run() 中的 x*=2 在方法 makeItSo 中的 x=x-1 和 System.out.println(x) 之间执行

事实并非如此。以下是发布的代码中发生的情况的解释:

1) 主线程创建一个 Starter 类型的新对象,首先将其实例变量 x 初始化为 2(变量初始化),然后(在构造函数中)将相同的实例变量设置为 5,并启动新线程。

2) 主线程调用方法 makeItSo(在构造函数调用创建的 Starter 实例上)并加入新线程,等待它完成。

3) 新线程执行它的 run 方法,将 x 加倍,然后完成(通知主线程它已经完成)。

4) 然后主线程唤醒,从 x 中减去 1,然后打印 9。

由于 x 是跨线程修改的,并且不是易失性或原子性的,并且不执行同步,因此新线程对 x 的更新是否保证对主线程可见并不明显(因此它是否适用于目的或意外情况不清楚),使 G 看起来是正确的答案。但是 join 会在新线程上进行同步(因为 join 是使用等待实现的,因此会锁定线程); x 的当前值将在主线程从 join 调用返回时可见。所以答案是D。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-05
    • 2020-11-02
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    相关资源
    最近更新 更多