Java併發原理學習筆記+總結+實戰(6)——可重入鎖

Java中常用的重入鎖

    java中重入鎖的定義是指可重複、遞歸調用的鎖,在得到同一個對象或類的前提下,外層使用鎖之後,在內層中依然可是使用且不會發生死鎖。其中最常見的關鍵字是synchronize和reentrantLock這兩個。

使用synchronize實現

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class MyLock implements Lock {

  private boolean isLocked = false;

  private Thread lockBy = null;

  private int lockCount = 0;

  @Override
  public synchronized void lock() {
    // ...

    Thread currentThread = Thread.currentThread(); // Thread-0

    while (isLocked && currentThread != lockBy) {
      try {
        wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    isLocked = true;
    lockBy = currentThread;
    lockCount++; // 1   2
  }

  @Override
  public synchronized void unlock() {
    if (lockBy == Thread.currentThread()) {
      lockCount--;  // 1  0

      if (lockCount == 0) {
        notify();
        isLocked = false;
      }
    }
  }

  @Override
  public void lockInterruptibly() throws InterruptedException {

  }

  @Override
  public boolean tryLock() {
    return false;
  }

  @Override
  public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
    // TODO Auto-generated method stub
    return false;
  }



  @Override
  public Condition newCondition() {
    // TODO Auto-generated method stub
    return null;
  }

}

 

public class Sequence {

  private MyLock lock = new MyLock();

  private int value;

  public int getNext() {
    lock.lock();
    value++;
    lock.unlock();
    return value;

  }

  public static void main(String[] args) {

    Sequence s = new Sequence();

    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          System.out.println(s.getNext());
        }
      }
    }).start();
    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          System.out.println(s.getNext());
        }
      }
    }).start();
    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          System.out.println(s.getNext());
        }
      }
    }).start();
    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          System.out.println(s.getNext());
        }
      }
    }).start();
    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          System.out.println(s.getNext());
        }
      }
    }).start();
  }

}

當第一個線程執行getNext()方法,得到了鎖,使lockBy等於當前線程,也就是說,執行的這個方法的線程獲得了這個鎖,每次while循環都會對lockCount變量加一,即當前獲得鎖的數量加一;當線程調用unlock()釋放鎖後,lockCount變量減一,當釋放了所有的鎖之後,才執行notify()方法喚醒線程。如果在執行這個方法時,有第二個線程想要執行這個方法,因爲lockBy不等於該線程,導致第二個線程進入了循環,不斷執行wait()方法。只有當第一個線程釋放了所有的鎖,並執行了notify()方法後,第二個線程才被喚醒,繼續執行。這就是可重入鎖的特點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章