日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java的reentrantlock_JAVA中ReentrantLock详解(转)

發布時間:2025/3/15 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java的reentrantlock_JAVA中ReentrantLock详解(转) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自https://www.cnblogs.com/java-learner/p/9651675.html

前言:本文解決的問題

RentrantLock與Synchronized區別

ReentrantLock特征

ReentrantLock類的方法介紹

1.什么是ReentrantLock

1.1ReentrantLock 與Synchronized區別

在面試中詢問ReentrantLock與Synchronized區別時,一般回答都是

ReentrantLock

ReentrantLock是JDK方法,需要手動聲明上鎖和釋放鎖,因此語法相對復雜些;如果忘記釋放鎖容易導致死鎖

ReentrantLock具有更好的細粒度,可以在ReentrantLock里面設置內部Condititon類,可以實現分組喚醒需要喚醒的線程

RenentrantLock能實現公平鎖

Synchronized

Synchoronized語法上簡潔方便

Synchoronized是JVM方法,由編輯器保證枷鎖和釋放

1.2ReentrantLock特征介紹

JAVA的java.util.concurrent框架中提供了ReentrantLock類(于JAVA SE 5.0時引入),ReentrantLock實現了lock接口,具體在JDK中的定義如下:

public class ReentrantLock implements Lock, java.io.Serializable {

public ReentrantLock() {

sync = new NonfairSync();

}

/**

* Creates an instance of {@code ReentrantLock} with the

* given fairness policy.

*

* @param fair {@code true} if this lock should use a fair ordering policy

*/

public ReentrantLock(boolean fair) {

sync = fair ? new FairSync() : new NonfairSync();

}

}

看到一個類首先就需要知道它的構造方法有哪些,ReentrantLock有兩個構造方法,一個是無參的?ReentrantLock();另一個含有布爾參數public ReentrantLock(boolean fair)。后面一個構造函數說明ReentrantLock可以新建公平鎖;而Synchronized只能建立非公平鎖。

那么Lock接口有哪些方法

Lock接口中有lock和unlock方法,還有newCondition() 方法,這就是上面說的ReentrantLock里面設置內部Condititon類。由于ReentrantLock實現了Lock接口,因此它必須實現該方法,具體如下:

public Condition newCondition() {

return sync.newCondition();

}

返回Condition類的一個實例。

2 ReentrantLock其它方法介紹

在介紹它的其它方法前,要先明白它的使用方法,以下JDK中的建議:

class X {

private final ReentrantLock lock = new ReentrantLock();

// ...

public void m() {

lock.lock(); // block until condition holds

try {

// ... method body

} finally {

lock.unlock()

}

}

建議用try,在finally里面一定要釋放鎖,防止被中斷時鎖沒釋放,造成死鎖

lock()

public void lock() {

sync.lock();

}

如果該鎖沒被其它線程獲得,則立即返回;并且把 lock hold count的值變位1.

unlock()

public void unlock() {

sync.release(1);

}

如果當前線程是該鎖的持有者,則保持計數遞減。 如果保持計數現在為零,則鎖定被釋放。 如果當前線程不是該鎖的持有者,則拋出IllegalMonitorStateException 。

isFair()

public final boolean isFair() {

return sync instanceof FairSync;

}

判斷該鎖是不是公平鎖

newCondition()

public Condition newCondition() {

return sync.newCondition();

}

返回新的ConditionObject對象。

Condition接口中的方法

await(): void await() throws InterruptedException;

Condition接口中的方法,導致當前線程等到發信號。

siginal()

/**

* Moves the longest-waiting thread, if one exists, from the

* wait queue for this condition to the wait queue for the

* owning lock.

*

* @throws IllegalMonitorStateException if {@link #isHeldExclusively}

* returns {@code false}

*/

public final void signal() {

if (!isHeldExclusively())

throw new IllegalMonitorStateException();

Node first = firstWaiter;

if (first != null)

doSignal(first);

}

喚醒一個等待該條件的線程去獲得鎖(第一個)。

signalAll():喚醒所有等待線程。

3 ReentrantLock完整實例介紹

package chapter10.reentrantlock;

import java.util.Arrays;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/*模擬轉賬,把錢從一個賬戶轉到另一個賬戶

* */

public class ReentrantLockUse {

public static final int NACCOUNTS = 100;

public static final double INITIAL_BALANCE = 1000;

public static final double MAX_AMOUNT = 1000;

public static final int DELAY = 10;

public static void main(String[] args) {

Bank bank = new Bank(NACCOUNTS,INITIAL_BALANCE);

for(int i = 0 ; i < NACCOUNTS ; i++) {

int fromAccount = i ;

Runnable r = () ->{//lambda表達式

try {

while(true) {

int toAccount = (int) (bank.size()*Math.random());

double amount = MAX_AMOUNT * Math.random();

bank.transfer(fromAccount, toAccount, amount);

Thread.sleep((int)(DELAY*Math.random()));

}

}

catch(InterruptedException e) {

}

};

Thread t = new Thread(r);//新建線程

t.start();

}

}

}

class Bank{

private final double[] account;//賬戶

private Lock bankLock ; //重復鎖

private Condition sufficientFunds; //條件對象

public Bank(int n, double initialBalance) {

account = new double[n];

Arrays.fill(account, initialBalance);

bankLock = new ReentrantLock(); //構造對象時,實例化鎖

sufficientFunds = bankLock.newCondition();//新建條件對象

}

/*轉賬,把from賬戶里面的錢轉到to里面,金額是amount*/

public void transfer(int from , int to,double amount) {

bankLock.lock();

try {

while(account[from] < amount) {

sufficientFunds.await();

}

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

account[from] -=amount;

System.out.printf("%10.2f from %d to %d ",amount,from,to);

account[to] +=amount;

System.out.printf(" Total Balance : %10.2f%n", getTotalBalance());

sufficientFunds.signalAll();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

finally {

bankLock.unlock();

}

}

/*做的所有賬戶總額*/

public double getTotalBalance() {

bankLock.lock();

try {

double sum = 0;

for(double a : account) {

sum +=a;

}

return sum;

}

finally {

bankLock.unlock();

}

}

public int size() {

return account.length;

}

}

執行結果

結果分析

循環建立100個線程,每個線程都在不停轉賬,由于ReentrantLock的使用,任何時刻所有賬戶的總額都保持不變。另外,把錢amount從A賬戶轉到B賬戶,要先判斷A賬戶中是否有這么多錢,不過沒有就調用條件對象ConditionObject中的await()方法,放棄該線程,等該其它線程轉錢進來;轉錢完成后調用.siginalAll()。

總結

以上是生活随笔為你收集整理的java的reentrantlock_JAVA中ReentrantLock详解(转)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。