为什么下面的代码增加值为2而不是1?(Java新手)

时间:2017-10-28 07:58:00

标签: java multithreading jvm synchronization thread-synchronization

在线程运行递增方法后的下面的代码中,它将值2输出到控制台。由于方法将值递增1,因此该值不是1吗?

class TestSync implements Runnable {
private int balance;

public void run() {

    for(int i = 0; i < 50; i++){

        increment();
        System.out.println(Thread.currentThread().getName() + " balance after increment is " +balance);
    }

}

private synchronized void increment() {

    int i = balance;
    balance = i + 1;
    // System.out.println(balance);
}

}

公共类TestSyncTest {

public static void main(String[] args) {

    TestSync job = new TestSync();
    Thread a = new Thread(job);
    Thread b = new Thread(job);
    a.setName("Thread A");
    b.setName("Thread B");

    a.start();
    b.start();

}

}

3 个答案:

答案 0 :(得分:0)

因为您的代码在循环中。而balance是全局数据。

在第一个循环中,balance的值为1

for (int i = 0; i < 50; i++) {

      increment();
      System.out.println(Thread.currentThread().getName() + " balance after increment is " + balance);
}

<强>输出

//          i       balance
//  first   0          1
//  second  1          2
//  third   2          3
//  ...

答案 1 :(得分:0)

您的增量方法已同步,但余额变量由线程共享。在第一个线程调用增量之后,在它可以打印平衡之前,另一个线程可以调用增量。将print语句放在increment方法中。

答案 2 :(得分:0)

两个线程共享同一个对象。唯一的同步方法会增加i的值,但不保证在打印值时他们将采取的顺序也不会保证打印它的状态。

如果您希望每个方法在增量后打印其值,请从同步方法取消注释sysout并将其从run()中删除。

如果您希望在打印前完成所有线程,则需要使用Thread.join()

这是一个简单的例子:

class TestSync implements Runnable {
    private int balance;

    public void run() {

        for(int i = 0; i < 50; i++){
            increment();
        }

    }

    private synchronized void increment() {

        int i = balance;
        balance = i + 1;
    }

    public void printBalance() ´{
        System.out.println("Balance: " + balance);
    }
}

public static void main(String[] args) {

    TestSync job = new TestSync();
    Thread a = new Thread(job);
    Thread b = new Thread(job);
    a.setName("Thread A");
    b.setName("Thread B");

    a.start();
    b.start();

    try {
      System.out.println("Wait for threads to finish.");
      a.join();
      b.join();
    } catch (InterruptedException e) {
      System.out.println("Interruption waiting for threads to finish.");
    }
    a.printBalance(); // either method will print the same value.
}