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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

聊聊高并发(二十七)解析java.util.concurrent各个组件(九) 理解ReentrantLock可重入锁

發(fā)布時間:2024/1/17 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 聊聊高并发(二十七)解析java.util.concurrent各个组件(九) 理解ReentrantLock可重入锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這篇講講ReentrantLock可重入鎖,JUC里提供的可重入鎖是基于AQS實現的阻塞式可重入鎖。這篇?聊聊高并發(fā)(十六)實現一個簡單的可重入鎖?模擬了可重入鎖的實現。可重入鎖的特點是:

1. 是互斥鎖,基于AQS的互斥模式實現,也就是說同時只有一個線程進入臨界區(qū),喚醒下一個線程時也只能釋放一個等待線程

2. 可重入,通過設置了一個字段exclusiveOwnerThread來標示當前獲得鎖的線程。獲取鎖操作是,如果當前線程是已經獲得鎖的線程,那么獲取操作成功。把當前狀態(tài)作為獲得鎖次數的計數器,重入一次就加1,釋放一次就減1,直到狀態(tài)為0

3. 1個可重入鎖可以關聯多個Condition條件對象來操作多個條件隊列。Condition接口提供了顯式阻塞/喚醒線程的條件隊列操作。這點比內置鎖和內置條件隊列更具靈活性,1個對象只有1個內置鎖和1個內置條件隊列。看這篇聊聊高并發(fā)(十四)理解Java中的管程,條件隊列,Condition以及實現一個阻塞隊列

?

來看看ReentrantLock的代碼。 它也提供了Sync類來繼承AQS,通過實現tryXXX來擴展功能。

1. nonfairTryAcquire()是非公平的tryAcquire操作,可以無視AQS等待隊列,直接通過判斷狀態(tài)來嘗試獲取鎖,并把當前線程設置為獲取鎖的線程來支持可重入性

2. tryRelease()方法通過修改狀態(tài)來釋放鎖,如果狀態(tài)為0,就把exclusiveOwnerThread設置為空,給之后線程競爭

3. newCondition() 方法每次都創(chuàng)建一個ConditionObject來表示1個條件隊列。在之前講AQS的文章中講了,從條件隊列喚醒后不是立刻獲得鎖,而是從條件隊列進入到了同步隊列,還是得競爭鎖。而隊列鎖的數據結構提供了先來先服務的特性,并且降低了鎖的爭用

?

?
  • abstract static class Sync extends AbstractQueuedSynchronizer {

  • private static final long serialVersionUID = -5179523762034025860L;

  • ?
  • /**

  • * Performs {@link Lock#lock}. The main reason for subclassing

  • * is to allow fast path for nonfair version.

  • */

  • abstract void lock();

  • ?
  • /**

  • * Performs non-fair tryLock. tryAcquire is

  • * implemented in subclasses, but both need nonfair

  • * try for trylock method.

  • */

  • final boolean nonfairTryAcquire(int acquires) {

  • final Thread current = Thread.currentThread();

  • int c = getState();

  • if (c == 0) {

  • if (compareAndSetState(0, acquires)) {

  • setExclusiveOwnerThread(current);

  • return true;

  • }

  • }

  • else if (current == getExclusiveOwnerThread()) {

  • int nextc = c + acquires;

  • if (nextc < 0) // overflow

  • throw new Error("Maximum lock count exceeded");

  • setState(nextc);

  • return true;

  • }

  • return false;

  • }

  • ?
  • protected final boolean tryRelease(int releases) {

  • int c = getState() - releases;

  • if (Thread.currentThread() != getExclusiveOwnerThread())

  • throw new IllegalMonitorStateException();

  • boolean free = false;

  • if (c == 0) {

  • free = true;

  • setExclusiveOwnerThread(null);

  • }

  • setState(c);

  • return free;

  • }

  • ?
  • protected final boolean isHeldExclusively() {

  • // While we must in general read state before owner,

  • // we don't need to do so to check if current thread is owner

  • return getExclusiveOwnerThread() == Thread.currentThread();

  • }

  • ?
  • final ConditionObject newCondition() {

  • return new ConditionObject();

  • }

  • ?
  • // Methods relayed from outer class

  • ?
  • final Thread getOwner() {

  • return getState() == 0 ? null : getExclusiveOwnerThread();

  • }

  • ?
  • final int getHoldCount() {

  • return isHeldExclusively() ? getState() : 0;

  • }

  • ?
  • final boolean isLocked() {

  • return getState() != 0;

  • }

  • ?
  • /**

  • * Reconstitutes this lock instance from a stream.

  • * @param s the stream

  • */

  • private void readObject(java.io.ObjectInputStream s)

  • throws java.io.IOException, ClassNotFoundException {

  • s.defaultReadObject();

  • setState(0); // reset to unlocked state

  • }

  • }

  • ?

    同樣提供了公平鎖和非公平鎖的FairSync和NonfairSync實現。和之前的Semaphore中公平性的含義一樣,非公平性體現在獲取操作時是否等待AQS隊列中的先來的線程,而一旦非公平獲取鎖失敗,那么就進入AQS隊列等待,AQS隊列是FIFO的隊列

    1. 可以看到非公平鎖的lock操作,先用最快路徑的方式嘗試了一次獲得鎖,如果獲取失敗,才用acquire操作調用AQS隊列

    2. 公平鎖的tryAcquire操作在狀態(tài)為0時要先等待先來的線程都是否后才能獲得鎖,如果有先來的線程,那么就進入AQS隊列。如果當前獲得鎖的線程是自己,就直接獲得鎖,把狀態(tài)加1,體現了可重入

    ?

    ?
  • static final class NonfairSync extends Sync {

  • private static final long serialVersionUID = 7316153563782823691L;

  • ?
  • /**

  • * Performs lock. Try immediate barge, backing up to normal

  • * acquire on failure.

  • */

  • final void lock() {

  • if (compareAndSetState(0, 1))

  • setExclusiveOwnerThread(Thread.currentThread());

  • else

  • acquire(1);

  • }

  • ?
  • protected final boolean tryAcquire(int acquires) {

  • return nonfairTryAcquire(acquires);

  • }

  • }

  • ?
  • /**

  • * Sync object for fair locks

  • */

  • static final class FairSync extends Sync {

  • private static final long serialVersionUID = -3000897897090466540L;

  • ?
  • final void lock() {

  • acquire(1);

  • }

  • ?
  • /**

  • * Fair version of tryAcquire. Don't grant access unless

  • * recursive call or no waiters or is first.

  • */

  • protected final boolean tryAcquire(int acquires) {

  • final Thread current = Thread.currentThread();

  • int c = getState();

  • if (c == 0) {

  • if (!hasQueuedPredecessors() &&

  • compareAndSetState(0, acquires)) {

  • setExclusiveOwnerThread(current);

  • return true;

  • }

  • }

  • else if (current == getExclusiveOwnerThread()) {

  • int nextc = c + acquires;

  • if (nextc < 0)

  • throw new Error("Maximum lock count exceeded");

  • setState(nextc);

  • return true;

  • }

  • return false;

  • }

  • }


  • 默認的ReentrantLock使用的是非公平鎖

    ?

    ?
  • public ReentrantLock() {

  • sync = new NonfairSync();

  • }


  • ReentrantLock提供了

    1. 可中斷和不可中斷的lock操作

    2. 提供了tryLock()方式非公平的獲取一次鎖,如果不成功就返回

    3. 提供了tryLock(long timeout, TimeUnit unit)的限時鎖

    ?

    ?

    ?
  • public void lock() {

  • sync.lock();

  • }

  • ?
  • ?public void lockInterruptibly() throws InterruptedException {

  • ??????? sync.acquireInterruptibly(1);

  • ??? }

  • ?
  • public boolean tryLock() {

  • ??????? return sync.nonfairTryAcquire(1);

  • ??? }

  • ?
  • public boolean tryLock(long timeout, TimeUnit unit)

  • ??????????? throws InterruptedException {

  • ??????? return sync.tryAcquireNanos(1, unit.toNanos(timeout));

  • ??? }

  • ?
  • public Condition newCondition() {

  • ??????? return sync.newCondition();

  • ??? }

  • 總結

    以上是生活随笔為你收集整理的聊聊高并发(二十七)解析java.util.concurrent各个组件(九) 理解ReentrantLock可重入锁的全部內容,希望文章能夠幫你解決所遇到的問題。

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