【问题标题】:Why does the below code increment value with 2 rather than 1?(New to Java)为什么下面的代码用 2 而不是 1 递增值?(Java 新手)
【发布时间】:2017-10-28 07:57:59
【问题描述】:

在下面的代码中,线程运行 increment 方法后,它会将值 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();

}

}

【问题讨论】:

  • 如果两个线程在它们中的任何一个打印出值之前递增值怎么办?
  • 尝试注释掉现有的System.out.println 并取消注释您现在已注释掉的那个。
  • 你能检查我的答案吗?

标签: java multithreading jvm synchronization thread-synchronization


【解决方案1】:

因为您的代码在循环中。而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
//  ...

【讨论】:

  • 我理解你试图解释的逻辑。打印语句输出的值以 2 而不是 1 开头,这让我很困惑。
  • 你可以自己调试,让你更容易理解
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    两个线程共享同一个对象。唯一同步的方法会增加 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.
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 2019-09-14
      相关资源
      最近更新 更多