转自https://www.cnblogs.com/java-learner/p/9651675.html
前言:本文解决的问题
RentrantLock与Synchronized区别ReentrantLock特征ReentrantLock类的方法介绍在面试中询问ReentrantLock与Synchronized区别时,一般回答都是
ReentrantLock
ReentrantLock是JDK方法,需要手动声明上锁和释放锁,因此语法相对复杂些;如果忘记释放锁容易导致死锁ReentrantLock具有更好的细粒度,可以在ReentrantLock里面设置内部Condititon类,可以实现分组唤醒需要唤醒的线程RenentrantLock能实现公平锁Synchronized
Synchoronized语法上简洁方便Synchoronized是JVM方法,由编辑器保证枷锁和释放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类的一个实例。
在介绍它的其它方法前,要先明白它的使用方法,以下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 hold count的值变位1.
如果当前线程是该锁的持有者,则保持计数递减。 如果保持计数现在为零,则锁定被释放。 如果当前线程不是该锁的持有者,则抛出IllegalMonitorStateException 。
判断该锁是不是公平锁
返回新的ConditionObject对象。
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():唤醒所有等待线程。执行结果
结果分析循环建立100个线程,每个线程都在不停转账,由于ReentrantLock的使用,任何时刻所有账户的总额都保持不变。另外,把钱amount从A账户转到B账户,要先判断A账户中是否有这么多钱,不过没有就调用条件对象ConditionObject中的await()方法,放弃该线程,等该其它线程转钱进来;转钱完成后调用.siginalAll()。
转载于:https://www.cnblogs.com/ffaiss/p/11431428.html