------- android培訓、java培訓、期待與您交流! ----------
當多個線程類共用同一變數時,若不加以控制,則程式會產生錯誤。比如銀行取錢這一業務,兩個取錢線程對同時賬戶進行取錢很有可能發生違背邏輯的地方。代碼如下:
package c16Thread;/** * 程式描述: * 一個Account類,代表銀行賬戶,一個Getting類,代表取錢者;用戶端持有Account實體,和兩個Getting線程類,兩個線程類對同一個賬戶進行操作 * 也就是說兩個線程共用同一個變數,程式示範不控制共用變數的情況下產生的業務錯誤 * @author renyajun * */public class TwoPersonOneAccount {public static void main(String[] args) {//1.擷取賬戶//2.建立一個存錢者和取錢者,對同一賬戶進行操作,觀察多線程對共用變數的安全問題。Acount a=new Acount();Getting r2=new Getting(a);Getting r1=new Getting(a);Thread tr2=new Thread(r2);Thread tr1=new Thread(r1);tr2.start();tr1.start();}}//Account類,代表銀行賬戶class Acount {private float balance=800;//餘額public float getBalance() {return balance;}public void setBalance(float balance) {this.balance = balance;}//向賬戶中增加錢public void depositMoney(float money){this.balance+=money;}//從賬戶中取錢public void reduceMoney(float money){this.balance-=money;}}//Getting類代表取錢行為,持有Account的引用,在建立時傳入class Getting implements Runnable {Acount acount;public Getting(Acount a){this.acount=a;}@Overridepublic void run() {if (acount.getBalance() != 0) {//判斷是否有錢後,讓線程等待1豪秒,如果不做同步,下一線程的reduceMoney()肯定會得到執行,//於是產生共用變數出錯。try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}acount.reduceMoney(800);System.out.println(acount.getBalance());} else {System.out.println("取錢失敗!");}}}
執行結果:
-800顯然違背了 if(account.getBalance()!=0)這句話規定的商務邏輯。
解決方案一:同步代碼塊
public void run() {synchronized (acount2) {if (acount2.getBalance() != 0) {//判斷是否有錢後,讓線程等待1豪秒,如果不做同步,下一線程的reduceMoney()肯定會得到執行,//於是產生共用變數出錯。try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}acount2.reduceMoney(800);System.out.println(acount2.getBalance());} else {System.out.println("取錢失敗!");}}