下面是一段有关Java线程的题目。

  以下是一个Java类的代码:

 1 public class Test {
 2 
 3     int a=0;
 4     int b=0;
 5     int x=0;
 6     int y=0;
 7 
 8     public static void main(String[] args) throws InterruptedException {
 9         Test test = new Test();
10         test.run();
11     }
12 
13     private void run() throws InterruptedException{
14         Thread th1 = new Thread(){
15             public void run(){
16                 a = 1;
17                 y = b;
18             }
19         };
20         th1.start();
21 
22         Thread th2 = new Thread(){
23             public void run(){
24                 b = 1;
25                 x = a;
26             }
27         };
28         th2.start();
29 
30         th1.join();
31         th2.join();
32 
33         System.out.println("x = " + x + ", y = " + y);
34     }
35 }

  运行后输出的结果是【  】

  A. x = 0, y = 0  B. x = 0, y = 1  C. x = 1, y = 0  D. x = 1, y = 1

 

  对于这道题目,答案可能会出现多种:

  a)对线程没有任何了解的人,给出的答案应该是C;

  b)对线程有了解的人,根据不同的理解程度,会给出的答案应该是B、C、D中的任意两个的组合或者三个全部选择上;

  c)对线程和JVM运行机制都有了解的人,答案只有一个ABCD。

 

  可能很多童鞋会有疑问了,为什么会出现A呢???

 

  我写了一段代码来连续运行了1000W次,出现ABCD的次数如下:

  A: 13, B: 240662, C: 9759320, D: 5

 

  下面我就来解释下为什么会出现以上各种可能(按照难易程度逐个解释):

  C. 这个最简单,在这里就不多解释了,JVM按照代码的先后顺序执行就是这个结果。

 

  B. 这里先解释下start这个方法。当程序调用start方法的时候,JVM会创建一个新的线程,在这时会调用线程内部的init方法。init方法会先由SecurityManager决定档期那线程执行哪些操作,没有则由当前线程取得对应的ThreadGroup线程树(其中已有主线程),然后init方法贩毒案它是否为守护线程,得到线程的优先级以及内部自动生成的nextThreadID和出示的stackSize。做完这些之后,当前线程处于就绪状态,这是将会有两个线程开始执行:一个是主线程,一个是主线程调用start方法创建的线程。新创建的线程会添加到ThreadGroup中,这时CPU会根据当前线程的优先级,通过时间片流转执行当前线程,时间片轮状的时间很短,所以感觉上是马上执行。

  所以在上面的代码中尽管线程th1在th2之前声明和调用start方法,但是由于线程优先级,有可能th2线程在th1线程之前运行,这样就执行后的结果就是B了。

 

  D. 当线程th1运行完第16行之后,由于CPU调度资源竞争等原因,可能接下来运行的就是线程th2,当运行完第24行后又去运行第17行代码,这样一来就会出现D的结果了。

 

  A. 对于A这个结果其实很多人都不解,其实原因说起来很简单。因为JVM在执行编译后的java代码时,在一个代码块中,如果改变执行顺序后不影响最终的结果,JVM不一定会按照代码顺序执行那段代码,也就是说第16行和第17行的代码,第24行和第25行代码的执行顺序有可能是颠倒的。然后参考D的解释就可以得到A这个答案了。

 

  到此结束,如果有哪里解释的不对,请拍砖,随时欢迎。

 

 

  来源:《Java并发编程实践》。

posted on 2011-09-30 09:38  Forest Wang  阅读(234)  评论(0编辑  收藏  举报