2017-03-03 110 views
1

我經歷了一本書,看到說,下面代碼的代碼是線程同步:同步在java中給人意想不到的輸出

// Account類

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。我的意思是他們應該是我的一些問題,因爲這兩個線程同時在同一個變量上工作。

請糾正我在哪裏錯了。 預先感謝

+1

這就是爲什麼你使用'同步' – QBrute

+0

其實,這本書是不完全正確的。您可以設置天平不同步。只有加和減是。你能告訴我們它是什麼書嗎? – Fildor

回答

0

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

0

在Java中會發生什麼情況是,每個對象都有一個intrisinc鎖,使用同步關鍵字表明,當一個線程(我們稱之爲A)調用這個方法,線程A持有鎖。當線程A持有鎖時,其他線程將被阻止訪問對象的同步部分(在您的情況下是Account對象)。

一旦線程A已完成執行(在這種情況下或方法)同步塊,線程A釋放對象上的鎖,以及其他線程正在等待訪問您的帳戶對象現在可以繼續前進。

  • 首先,它是不可能的同一對象上同步方法來交錯兩個調用。當一個線程正在執行 同步方法爲對象,即調用 針對同一對象塊同步方法所有其他線程,直到第一線程與對象進行(暫停執行) 。
  • 其次,當一個同步方法退出時,它自動地建立一個之前發生的關係與任何後續 調用針對同一對象同步方法進行說明。此 保證對所有 線程都可見對象狀態的更改。

上使用的同步詳情見https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

實際上使帳戶線程安全的,你會希望有二傳手同步和平衡被聲明爲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更多關於不穩定的使用。