0

我有以下代码,但它的输出不是我所期望的:

public class ThreadManager {
    public static void main(String[] args) {
        Resource sharedResource = new Resource();
        new Thread(new MyThread(sharedResource)).start();
        new Thread(new MyThread(sharedResource)).start();
    }
}

class MyThread implements Runnable{
    Resource rs = null;
    public MyThread(Resource param) {
        this.rs = param;
    }
    @Override
    public void run() {
        this.rs.add(Thread.currentThread().getName());
        System.out.println(this.rs.str);
    }
}

class Resource{
    StringBuilder str = new StringBuilder();
    public void add(String text){
        str.append(text);
    }
}

输出是:

Thread-0Thread-1
Thread-0Thread-1

但是怎么...

这里如果线程0首先执行,那么输出应该是

Thread-0
Thread-0Thread-1

但这里的问题是第一行输出中的线程 1。

4

2 回答 2

2

这里如果线程0先执行然后输出

是什么让您认为仅仅因为您首先启动线程 0,它就会首先到达add方法调用?即使一个线程确实首先到达add调用,这并不意味着它会在另一个线程有机会调用之前到达下一个语句 ( ) 。看起来这就是这里的情况:System.out.printlnadd

  • 线程0调用add
  • 线程 1 调用add
  • 线程0调用System.out.println(this.rs.str)
  • 线程 1 调用System.out.println(this.rs.str)

(这有点手动,因为这些不是原子操作,但它是一个可能的流程。)

想象你的两条线是跑道上的运动员——你开始它们的顺序不一定与它们穿过终点线的顺序相同。

另请注意,StringBuilder它的设计并不是为了从多个线程访问安全。

于 2012-10-07T08:38:35.090 回答
0

它并不像看起来那么简单。线程正在 printLn() 内的锁上交换,

于 2012-10-07T08:49:01.843 回答