JAVA中ReentrantLock详解
2021-06-27 14:03
标签:amount get bank with rgs img tac returns util 前言:本文解决的问题 在面试中询问ReentrantLock与Synchronized区别时,一般回答都是 ReentrantLock Synchronized JAVA的java.util.concurrent框架中提供了ReentrantLock类(于JAVA SE 5.0时引入),ReentrantLock实现了lock接口,具体在JDK中的定义如下: 看到一个类首先就需要知道它的构造方法有哪些,ReentrantLock有两个构造方法,一个是无参的 ReentrantLock() ;另一个含有布尔参数public ReentrantLock(boolean fair)。后面一个构造函数说明ReentrantLock可以新建公平锁;而Synchronized只能建立非公平锁。 那么Lock接口有哪些方法 返回Condition类的一个实例。 在介绍它的其它方法前,要先明白它的使用方法,以下JDK中的建议: 建议用try,在finally里面一定要释放锁,防止被中断时锁没释放,造成死锁 如果该锁没被其它线程获得,则立即返回;并且把 lock hold count的值变位1. 如果当前线程是该锁的持有者,则保持计数递减。 如果保持计数现在为零,则锁定被释放。 如果当前线程不是该锁的持有者,则抛出IllegalMonitorStateException 。 判断该锁是不是公平锁 返回新的ConditionObject对象。 await(): void await() throws InterruptedException; 唤醒一个等待该条件的线程去获得锁(第一个)。 执行结果 结果分析 JAVA中ReentrantLock详解 标签:amount get bank with rgs img tac returns util 原文地址:https://www.cnblogs.com/java-learner/p/9651675.html
1.什么是ReentrantLock
1.1ReentrantLock 与Synchronized区别
1.2ReentrantLock特征介绍
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();
}
}
Lock接口中有lock和unlock方法,还有newCondition() 方法,这就是上面说的ReentrantLock里面设置内部Condititon类。由于ReentrantLock实现了Lock接口,因此它必须实现该方法,具体如下: public Condition newCondition() {
return sync.newCondition();
}
2 ReentrantLock其它方法介绍
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
lock()
public void lock() {
sync.lock();
}
unlock()
public void unlock() {
sync.release(1);
}
isFair()
public final boolean isFair() {
return sync instanceof FairSync;
}
newCondition()
public Condition newCondition() {
return sync.newCondition();
}
Condition接口中的方法
Condition接口中的方法,导致当前线程等到发信号。 /**
* 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);
}
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 {//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]
循环建立100个线程,每个线程都在不停转账,由于ReentrantLock的使用,任何时刻所有账户的总额都保持不变。另外,把钱amount从A账户转到B账户,要先判断A账户中是否有这么多钱,不过没有就调用条件对象ConditionObject中的await()方法,放弃该线程,等该其它线程转钱进来;转钱完成后调用.siginalAll()。