簡體   English   中英

java中的同步給出了意外的輸出

[英]Synchronization in java giving unexpected output

我正在閱讀一本書並看到一段代碼,該代碼表明下面的代碼是線程同步的:

//帳戶類

 public class Account {

 private double balance;

 public double getBalance() {
 return balance;
}

 public void setBalance(double balance) {
 this.balance = balance;
}


 public synchronized void addAmount(double amount) {
 double tmp=balance;
 try {
 Thread.sleep(10);
 } catch (InterruptedException e) {
   e.printStackTrace();
 }
 tmp+=amount;
 balance=tmp;
}


public synchronized void subtractAmount(double amount) {
  double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp-=amount;
balance=tmp;
}

}

//銀行班

public class Bank implements Runnable {

 private Account account;
 public Bank(Account account) {
  this.account=account; 
}

@Override

public void run() {

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

     account.subtractAmount(1000);
  }
 }
}

//公司課程

public class Company implements Runnable {

 private Account account;

 public Company(Account account) {
    this.account=account;
}

@Override

 public void run() {
   for (int i=0; i<1000; i++){
   account.addAmount(1000);
   }
  }
}

//主要課程

 public class Main {
 public static void main(String[] args) {
 Account account=new Account();
 account.setBalance(1000);
 Company company=new Company(account);
 Thread companyThread=new Thread(company);
 Bank bank=new Bank(account);
 Thread bankThread=new Thread(bank);
 System.out.printf("Account : Initial Balance: %f\n",account.
 getBalance());
 companyThread.start();
 bankThread.start();

 try {
   companyThread.join();
   bankThread.join();
   System.out.printf("Account : Final Balance: %f\n",account.
   getBalance());
 } 
    catch (InterruptedException e) {
    e.printStackTrace();
  }
 }
}

這里兩個不同對象的兩個線程正在使用addAmount和subtractAmount函數同時更改平衡變量,但它總是給出正確的輸出作為初始和最終余額相同,即1000.000。 我的意思是他們應該有一些問題,因為兩個線程同時處理同一個變量。

請糾正我出錯的地方。 預先感謝

這就是同步的重點。 它確保一次只有一個線程可以執行該功能。

在Java中發生的事情是每個對象都有一個intrisinc鎖,並且使用synchronize關鍵字表示當一個Thread(讓我們稱之為A)調用該方法時,線程A持有鎖。 當線程A持有鎖時,其他線程將被阻止訪問Object的同步部分(在您的情況下為Account對象)。

一旦線程A完成了同步塊(或本例中的方法)的執行,線程A就會釋放對象的鎖定,等待訪問您的Account對象的其他線程現在可以繼續前進。

  • 首先,對同一對象的兩個同步方法的調用不可能進行交錯。 當一個線程正在為對象執行同步方法時,所有其他線程調用同一對象的同步方法(暫停執行)直到第一個線程完成對象。
  • 其次,當同步方法退出時,它會自動與同一對象的同步方法的任何后續調用建立先發生關系。 這可以保證對所有線程都可以看到對象狀態的更改。

有關使用synchronized的更多信息,請參閱https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

實際上,為了使Account線程安全,您可能希望將setter同步並將余額聲明為volatile:

public class Account {

 private volatile double balance;

 public double getBalance() {
 return balance;
 }

 public synchronized void setBalance(double balance) {
 this.balance = balance;
}

//其余代碼已經同步}

有關易失性使用的更多信息,請參閱https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM