Java多線程同步1——使用synchronized 代碼塊

關(guān)于多線程同步問題我們可以借用一個(gè)銀行取錢的實(shí)例來說明問題。

在這里我們簡單的建立一個(gè)類來代表銀行賬戶,代碼如下

public class Account {

// 賬號(hào)

private String accountNo;

//余額

private double balance;

public Account(){}

// 構(gòu)造器

public Account(String accountNo , double balance)

{

this.accountNo = accountNo;

this.balance = balance;

}

// accountNo的setter和getter方法

public void setAccountNo(String accountNo)

{

this.accountNo = accountNo;

}

public String getAccountNo()

{

return this.accountNo;

}

// balance的setter和getter方法

public void setBalance(double balance)

{

this.balance = balance;

}

public double getBalance()

{

return this.balance;

}

// 下面兩個(gè)方法根據(jù)accountNo來重寫hashCode()和equals()方法

public int hashCode()

{

return accountNo.hashCode();

}

public boolean equals(Object obj)

{

if(this == obj)

return true;

if (obj !=null

&& obj.getClass() == Account.class)

{

Account target = (Account)obj;

return target.getAccountNo().equals(accountNo);

}

return false;

}

}


建立一個(gè)取錢的線程類

public class DrawThread extends Thread

{

private Account account;

private double drawAmount;

public DrawThread(String name , Account account

, double drawAmount)

{

super(name);

this.account = account;

this.drawAmount = drawAmount;

}

public void run()

{

if (account.getBalance() >= drawAmount)

{

System.out.println(getName()

+ "取錢成功!吐出鈔票" + drawAmount);

try

{

Thread.sleep(1);

}

catch (InterruptedException ex)

{

ex.printStackTrace();

}

account.setBalance(account.getBalance() - drawAmount);

System.out.println("\t余額為:" + account.getBalance());

}

else

{

System.out.println(getName() + "取錢失??!余額不足");

}

}

}


在建立一個(gè)測(cè)試類模仿2個(gè)人對(duì)同一個(gè)賬戶進(jìn)行取錢

public class DrawTest

{

public static void main(String[] args)

{

Account acct = new Account("1234567" , 1000);

new DrawThread("甲" , acct , 800).start();

new DrawThread("乙" , acct , 800).start();

}

}

運(yùn)行結(jié)果有可能出現(xiàn)如下圖所示的情況



問題來了:賬戶余額只有1000時(shí)取出了1600塊,而且賬戶余額出現(xiàn)了負(fù)值,這不是我們希望得到的結(jié)果。


這是因?yàn)閞un()方法的方法體不具備同步安全性——程序中有兩個(gè)并發(fā)線程在修改Account對(duì)象,

為了解決這個(gè)問題,java多線程引入了同步監(jiān)視器來解決這個(gè)問題,使用同步監(jiān)視器的通用方法就是同步代碼塊。

synchronized (obj){

}

上面語法格式中的synchronized括號(hào)里面的obj就是同步監(jiān)視器,上面代碼的含義是:線程開始執(zhí)行

同步之前,必須先獲得同步監(jiān)視器的鎖定
將上面的代碼做如下修改


public class DrawThread extends Thread

{

private Account account;

private double drawAmount;

public DrawThread(String name , Account account

, double drawAmount)

{

super(name);

this.account = account;

this.drawAmount = drawAmount;

}

public void run()

{

synchronized (account)

{

if (account.getBalance() >= drawAmount)

{

System.out.println(getName()

+ "取錢成功!吐出鈔票:" + drawAmount);

try

{

Thread.sleep(1);

}

catch (InterruptedException ex)

{

ex.printStackTrace();

}

account.setBalance(account.getBalance() - drawAmount);

System.out.println("\t余額為: " + account.getBalance());

}

else

{

System.out.println(getName() + "取錢失??!余額不足");

}

}

}

}

運(yùn)行代碼得到如下結(jié)果:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容