Java线程混乱,为什么输出没有排序?

时间:2016-04-09 09:15:56

标签: java multithreading

查看输出,尽管使方法同步,但输出不是有序的。由于两个线程都在堆上递增相同的对象“作业”,无论哪个线程打印该行,结果都应该是增加的值。但为什么它会以无序方式打印?

class TestSync implements Runnable{
  private int balance;

  public void run(){
    for(int i=0; i<50; i++) {
      increment();   
    System.out.println("balance is "+balance);
    }
  }
  public synchronized void increment(){
   balance++;     
  }
}


public class TestSyncTest {

  public static void main(String[] args){
    TestSync job = new TestSync();
    Thread a = new Thread(job);
    Thread b = new Thread(job);
    a.start();
    b.start();
  }
}

输出:

balance is 2
balance is 3
balance is 4
balance is 5
balance is 6
balance is 7
balance is 8
balance is 9
balance is 10
balance is 11
balance is 12
balance is 13
balance is 14
balance is 15
balance is 16
balance is 17
balance is 18
balance is 19
balance is 20
balance is 21
balance is 22
balance is 23
balance is 24
balance is 2
balance is 25
balance is 27
balance is 28
balance is 29
balance is 26
balance is 30
balance is 32
balance is 33
balance is 34
balance is 35
balance is 36
balance is 37
balance is 31
balance is 38
balance is 40
balance is 41
balance is 42
balance is 43
balance is 44
balance is 39
balance is 46
balance is 47
balance is 45
balance is 49
balance is 48
balance is 50
balance is 52
balance is 51
balance is 53
balance is 55
balance is 54
balance is 56
balance is 58
balance is 59
balance is 60
balance is 57
balance is 61
balance is 62
balance is 63
balance is 64
balance is 65
balance is 66
balance is 67
balance is 68
balance is 69
balance is 70
balance is 71
balance is 72
balance is 73
balance is 74
balance is 75
balance is 76
balance is 77
balance is 78
balance is 79
balance is 80
balance is 81
balance is 82
balance is 83
balance is 84
balance is 85
balance is 86
balance is 87
balance is 88
balance is 89
balance is 90
balance is 91
balance is 92
balance is 93
balance is 94
balance is 95
balance is 96
balance is 97
balance is 98
balance is 99
balance is 100

3 个答案:

答案 0 :(得分:2)

唯一同步的是增量。在打印之前读取变量不是,并且打印本身在另一个锁上同步。所以你可以得到

  • 主题1:增量
  • 主题2:增量
  • 主题1:阅读并打印
  • 主题2:阅读并打印

BTW,余额是共享状态,全部访问,包括读取变量的值,应该在同一个锁上同步。

将代码更改为

class TestSync implements Runnable{
    private int balance;

    public void run(){
        for(int i = 0; i < 50; i++) {
            incrementAndPrint();   
        }
    }

    public synchronized void incrementAndPrint(){
        balance++;     
        System.out.println("balance is "+balance);
    }
}

答案 1 :(得分:0)

synchronized仅保护块同步。如果你在你的程序周围撒上一个小线程,它会做你想要的,这是一个常见的错误。线程安全就像一系列操作,如果没有同步,你的代码可以按任何顺序执行。

  

但为什么它会以无序的方式打印?

线程的目的是同时运行独立的任务。因此,您应该期望有一个或另一个线程比另一个线程执行得更快的时间。

真正的问题应该是;为什么它有条不紊。

这很可能是由于一个线程在另一个线程之前启动。当一个线程正在运行而另一个线程尚未启动时,输出是“有序的”,但是一旦两个线程都在运行,您就可以看到竞争条件。

答案 2 :(得分:0)

你有2个线程打印一个计数器,该应用程序正常工作,因为你可以看到每个线程都在控制台中打印,一旦想要给出计数器值,看起来像混合因为没有简单的方法格式化或识别来自哪个线程的值......

为每个帖子添加一个名称并打印名称,这样就可以看到数据的来源......

Thread a = new Thread(job, "t1");
Thread b = new Thread(job, "t2");