Detailed ReentrantLock in JAVA (rpm)

Transfer from https://www.cnblogs.com/java-learner/p/9651675.html

Preface: This article addresses the problem of

  • RentrantLock and Synchronized difference
  • ReentrantLock feature
  • The method of introduction class ReentrantLock

1. What is ReentrantLock

1.1ReentrantLock and Synchronized difference

When asked the difference Synchronized ReentrantLock in the interview, the general answer is

ReentrantLock

  • ReentrantLock is JDK method, you need to manually lock and release the lock statement, so the syntax is relatively complicated; if you forget to release a lock easily lead to deadlocks
  • ReentrantLock better fine-grained, may be provided inside the inner Condititon ReentrantLock class, packets need to wake wake threads can be achieved
  • RenentrantLock to achieve a fair lock

Synchronized

  • The syntax is simple and convenient on Synchoronized
  • Synchoronized the JVM method, by the editor to ensure shackles and release

1.2ReentrantLock features introduced

JAVA is provided in the framework java.util.concurrent ReentrantLock class (JAVA SE 5.0 is introduced in), ReentrantLock achieve lock interface in JDK specifically defined as follows:

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(); } }

See a first class needs to know what its constructor, of ReentrantLock two constructors, one is no argument  of ReentrantLock ()  ; further comprising a Boolean parameter public of ReentrantLock (Boolean Fair) . Behind a Constructor ReentrantLock can create fair locks ; and Synchronized only create unfair lock .

So what methods the interface Lock
lock
Lock interface has lock and unlock methods, as well as newCondition () method, which is above that ReentrantLock set up inside the internal Condititon class . Lock ReentrantLock achieved since the interface, it must implement this method, as follows:

  public Condition newCondition() {
        return sync.newCondition(); } 

Condition returns an instance of the class.

Other methods described 2 ReentrantLock

Before its introduction other methods, you must first understand its use, JDK in the following recommendations:

 class X {
     private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } 

Suggested try, there must be at finally releases the lock, the lock did not prevent the release is interrupted, resulting in deadlock

lock()

 public void lock() { sync.lock(); }

If the lock has not been obtained by other threads, immediately returned; and the value of the displacement of a lock hold count.

unlock()

 public void unlock() { sync.release(1); } 

If the current thread is the lock holder, leave counting down. If the holding count is now zero, the lock is released. If the current thread is not the lock holder, is thrown IllegalMonitorStateException.

isFair ()

public final boolean isFair() { return sync instanceof FairSync; }

This is not a fair judge lock lock

newCondition ()

 public Condition newCondition() {
        return sync.newCondition(); }

Returns a new ConditionObject object.

Condition Interface Method

  • await (): void await () throws InterruptedException;
    Method Condition interface, causes the current thread to wait until the signal.

  • (signal)
 /**
         * 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); }

Wake up a thread waiting for the condition to obtain the lock (the first).

  • signalAll (): wake up all waiting threads.

3 ReentrantLock complete example introduction

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; } } 

Results of the
reentrantLOck execution results

Result Analysis
circulation within 100 threads, each are constantly transfers, due to the use ReentrantLock, the total of all accounts at any time remain unchanged. In addition, the amount of money from account A to account B, must first determine whether there is so much money in the account A, but not to call await () method in the condition of the object ConditionObject, abandon the thread, and other money coming in the other thread turn ; after the completion of the money transfer calls .siginalAll ().

Guess you like

Origin www.cnblogs.com/ffaiss/p/11431428.html