1. 程式人生 > >JUC——線程同步鎖(ReentrantLock)

JUC——線程同步鎖(ReentrantLock)

spa his 進入 star zab serial 進行 zed util

ReentrantLock簡介

ReentrantLock是一個可重復的互斥鎖,又被稱為獨占鎖,可重入的意思是:ReentrantLock鎖可以被單個線程多次獲取。但是在同一個時間點只能被一個線程鎖持有

ReentrantLock使用一個FIFO(先進先出)的等待隊裏來管理獲取該鎖所有線程的。

ReentrantLock是一個獨占鎖,在獲取鎖的之後其所有的操作都是線程獨享的,其他的線程在沒有獲取到鎖之前都需要等待。

public class ReentrantLock implements Lock,java.io.Serializable

ReentrantLock之中分為公平鎖與非公平鎖,它們的區別體現在獲取鎖的機制上是否公平以及執行速度上。、

這兩種鎖的啟用也是非常容易控制的,這個類提供的構造方法如下:

  • 無參構造(非公平鎖,NonfairSync)
    public ReentrantLock() {
        sync = new NonfairSync();
    }
  • 有參構造
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    //fair = true,表示公平鎖,FairSync
    //fair = false,表示非公平鎖,NonfairSync

ReentrantLock繼承結構

技術分享圖片

範例:使用ReentrantLock定義一個多線程賣票的處理程序

package so.strong.mall.concurrent;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Ticket {
    private Lock myLock = new ReentrantLock();  //非公平鎖
    private int count = 10; //一共10張票
    public void sale() {
        myLock.lock(); //進入到阻塞狀態,一直到unlock執行後解除阻塞
try { if (this.count > 0) { System.out.println(Thread.currentThread().getName() + "賣票,ticket=" + this.count--); } } finally { myLock.unlock(); //不管最終結果如何一定要進行解鎖 } } } public class TestDemo { public static void main(String[] args) { final Ticket ticket = new Ticket(); //多線程要共享同一個數據資源 for (int i = 0; i < 6; i++) { new Thread(new Runnable() { @Override public void run() { while (true) { ticket.sale(); //賣票處理 } } }).start(); } } }
Thread-0賣票,ticket=10
Thread-0賣票,ticket=9
Thread-0賣票,ticket=8
Thread-0賣票,ticket=7
Thread-0賣票,ticket=6
Thread-0賣票,ticket=5
Thread-0賣票,ticket=4
Thread-2賣票,ticket=3
Thread-2賣票,ticket=2
Thread-2賣票,ticket=1

當前的代碼要比直接使用synchronized更加容易,而且鎖的處理機制更加的直觀。通過查看源代碼可以發現,使用lock()進行鎖定的時候會考慮兩種情況:

Sync-java.util.concurrent.locks.ReentrantLock

  • FairSync-java.util.concurrent.locks.ReentrantLock
  • NonFairSync-java.util.concurrent.locks.ReentrantLock

在進行公平鎖處理的時候每當鎖定一個線程對象就會使用“acquire(1)”方法進行表示:

final void lock() {
   if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
   else
        acquire(1);
}

在進行解鎖時會使用一個"sync.release(1)”釋放方法, 1 表示釋放一個:

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

JUC——線程同步鎖(ReentrantLock)