Java多線程同步3——同步鎖

Java提供了一種更強(qiáng)大的線程同步機(jī)制——通過(guò)顯示定義同步鎖對(duì)象來(lái)實(shí)現(xiàn)同步,同步鎖由Lock對(duì)象充當(dāng)。

Lock是控制多個(gè)線程對(duì)共享資源進(jìn)行訪問(wèn)的工具。通常,鎖提供了對(duì)共享資源的獨(dú)立訪問(wèn),每次只能有一個(gè)線程對(duì)Lock對(duì)象加鎖,線程開(kāi)始訪問(wèn)共享資源之前應(yīng)先獲得Lock對(duì)象

在實(shí)現(xiàn)線程安全的控制中,比較常用的是ReentrantLock(可重寫(xiě)入鎖)。使用該Lock對(duì)象可以顯示地加鎖,釋放鎖,通常使用ReentrantLock格式如下:

class x{

? private final ReentrantLock lock=new ReentrantLock();

?public void m(){

lock.lock();

try{

//需要保證線程安全的代碼

}finally{

lock.unlock();

}

}


}


通過(guò)使用ReentrantLock的方法修改前文所提到的取錢(qián)問(wèn)題。

package com.eduask.java.thread.sync.lock;

import java.util.concurrent.locks.*;

public class Account

{

// 定義鎖對(duì)象

private final ReentrantLock lock = new ReentrantLock();

// // 封裝賬戶編號(hào)、賬戶余額的兩個(gè)成員變量

private String accountNo;

private double balance;

public Account(){}

// 構(gòu)造器

public Account(String accountNo , double balance)

{

this.accountNo = accountNo;

this.balance = balance;

}

public void setAccountNo(String accountNo)

{

this.accountNo = accountNo;

}

public String getAccountNo()

{

return this.accountNo;

}

public double getBalance()

{

return this.balance;

}

// 提供一個(gè)線程安全draw()方法來(lái)完成取錢(qián)操作

public void draw(double drawAmount)

{

// 加鎖

lock.lock();

try

{

// 賬戶余額大于取錢(qián)數(shù)目

if (balance >= drawAmount)

{

System.out.println(Thread.currentThread().getName()

+ "取錢(qián)成功!吐出鈔票:" + drawAmount);

try

{

Thread.sleep(1);

}

catch (InterruptedException ex)

{

ex.printStackTrace();

}

// 修改余額

balance -= drawAmount;

System.out.println("\t余額為" + balance);

}

else

{

System.out.println(Thread.currentThread().getName()

+ "取錢(qián)失敗!余額不足!");

}

}

finally

{

// 修改完成,釋放鎖

lock.unlock();

}

}

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;

}

}


模仿取錢(qián)的多線程

package com.eduask.java.thread.sync.lock;

public class DrawThread extends Thread

{

// 模擬用戶賬戶

private Account account;

// 當(dāng)前取錢(qián)線程所希望取的錢(qián)數(shù)

private double drawAmount;

public DrawThread(String name , Account account

, double drawAmount)

{

super(name);

this.account = account;

this.drawAmount = drawAmount;

}

public void run()

{

account.draw(drawAmount);

}

}

測(cè)試類

package com.eduask.java.thread.sync.lock;

public class DrawTest

{

public static void main(String[] args)

{

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

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

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

}

}

結(jié)果:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容