java 同步方式 lock_Java的同步锁(Lock)
從Java 5開始,Java提供了一種功能更強大的線程同步機制一-通過 顯式定義同步鎖對象來實現同步,在這種機制下,同步鎖由Lock對象充當。Lock提供了比synchronized方法和synchronized代碼塊更廣泛的鎖定操作,Lock 允許實現更靈活的結構,可以具有差別很大的屬性,并且支持多個相關的Condition對象。
Lock是控制多個線程對共享資源進行訪問的工具。通常,鎖提供了對共享資源的獨占訪問,每次只能有一個線程對Lock對象加鎖,線程開始訪問共享資源之前應先獲得Lock對象。某些鎖可能允許對共享資源并發訪問,如ReadWriteLock (讀寫鎖), Lock、 ReadWriteLock是Java 5提供的兩個根接口,并為Lock提供了ReentrantLock (可重入鎖)實現類,為ReadWriteLock 提供了ReentrantReadWriteLock實現類。
Java 8新增了新型的StampedLock類,在大多數場景中它可以替代傳統ReentrantReadWriteLock.
ReentrantReadWriteLock為讀寫操作提供了三種鎖模式: Writing、 ReadingOptimistic、Reading。
在實現線程安全的控制中,比較常用的是ReentrantLock (可重入鎖)。使用該Lock對象可以顯式地加鎖、釋放鎖,通常使用ReentrantLock的代碼格式如下:
classx{
//定義鎖對象
privatefinalReentrantLocklock=newReentrantLock();
//定義需要保證線程安全的方法
publicvoidm(){
//加鎖
lock.lock();
try{
//需要保證線程安全的代碼
//... method body
//使用finally塊來保證釋放鎖
}finally{
lock.unlock();
}
}
使用ReentrantLock 對象來進行同步,加鎖和釋放鎖出現在不同的作用范圍內時,通常建議使用finally塊來確保在必要時釋放鎖。通過使用ReentrantLock 對象,可以把Account 類改為如下形式,它依然是線程安全的。
publicclassAccount
{
//定義鎖對象
privatefinalReentrantLocklock=newReentrantLock();
privateStringaccountNo;
privatedoublebalance;
publicAccount(){}
publicAccount(StringaccountNo,doublebalance)
{
this.accountNo=accountNo;
this.balance=balance;
}
publicvoidsetAccountNo(StringaccountNo)
{
this.accountNo=accountNo;
}
publicStringgetAccountNo()
{
returnthis.accountNo;
}
publicdoublegetBalance()
{
returnthis.balance;
}
publicvoiddraw(doubledrawAmount)
{
lock.lock();
try
{
//賬戶余額大于取錢數目
if(balance>=drawAmount)
{
//吐出鈔票
System.out.println(Thread.currentThread().getName()+
"取錢成功!吐出鈔票:"+drawAmount);
try
{
Thread.sleep(1);
}
catch(InterruptedExceptionex)
{
ex.printStackTrace();
}
//修改余額
balance-=drawAmount;
System.out.println("\t余額為: "+balance);
}
else
{
System.out.println(Thread.currentThread().getName()+
"取錢失敗!余額不足!");
}
}
finally
{
lock.unlock();
}
}
publicinthashCode()
{
returnaccountNo.hashCode();
}
publicbooleanequals(Objectobj)
{
if(obj!=null&&obj.getClass()==Account.class)
{
Accounttarget=(Account)obj;
returntarget.getAccountNo().equals(accountNo);
}
returnfalse;
}
}
上面程序中的第一行粗體字代碼定 義了-個ReentrantLock對象,程序中實現draw()方法時,進入方法開始執行后立即請求對ReentrantLock 對象進行加鎖,當執行完draw()方法的取錢邏輯之后,程序使用finally塊來確保釋放鎖。
其他:
同步方法或同步代碼塊使用與競爭資源相關的、隱式的同步監視器,并且強制要求加鎖和釋放鎖要出現在一個塊結構中,而且當獲取了多個鎖時,它們必須以相反的順序釋放,且必須在與所有鎖被獲取時相同的范圍內釋放所有鎖。
雖然同步方法和同步代碼塊的范圍機制使得多線程安全編程非常方便而且還可以避免很多涉及鎖的常見編程錯誤,但有時也需要以更為靈活的方式使用鎖。Lock 提供了同步方法和同步代碼塊所沒有的其他功能,包括用于非塊結構的tryLock()方法,以及試圖獲取可中斷鎖locknterruptibly()方法,還有獲取超時失效鎖的tryLock(long, TimeUni)方法。
ReentrantLock鎖具有可重入性,也就是說,-一個線程可以對已被加鎖的ReentrantLock鎖再次加鎖,ReentrantLock對象會維持 一個計數器來追蹤lock()方法的嵌套調用,線程在每次調用lock(加鎖后,必須顯式調用unlock(來釋放鎖,所以一段被鎖保護的代碼可以調用另一個被相同鎖保護的方法。
總結
以上是生活随笔為你收集整理的java 同步方式 lock_Java的同步锁(Lock)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pdfparser java_如何使用j
- 下一篇: python 字典的值可以为集合吗_转: