1. 程式人生 > >顯示鎖ReentrantLock和Condition的使用

顯示鎖ReentrantLock和Condition的使用

一、ReentrantLock
(1)、java.util.concurrent.locks包中的ReentrantLock就是重入鎖,它實現了Lock介面,Lock加鎖和解鎖都是顯示的。ReentrantLock重入鎖可以實現synchronized關鍵字的功能。
主要方法:
lock:獲得鎖。
unlock:釋放鎖。
(2)、java對synchronized優化之後,ReentrantLock和synchronize大的區別:
a、鎖的粒度,ReentrantLock更細,更靈活。
b、ReentrantLock可以指定鎖的公平性。synchronize只能是非公平的。
c、ReentrantLock可以利用Condition(條件)類選擇性分組喚醒執行緒。
d、ReentrantLock可以中斷一個正在等待獲取鎖的執行緒。lockInterruptibly()。
(3)、典型的使用格式:

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

測試i++的程式碼:
注意:必須在finally塊中呼叫unlock語句釋放鎖,以確保即使在方法體中丟擲異常(try塊)鎖也會釋放鎖。否則這個鎖永遠不釋放。

/**
 * @author tangquanbin
 * @date 2018/12/16 22:24
 */
public class ReentrantLockService{

    private Lock lock = new ReentrantLock();
    private int count = 0;

    public void getCount(){
        try {
            //獲得鎖
            lock.lock();
            System.out.println("thread :"+Thread.currentThread().getName()+" count = "+count++);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //在finally塊中呼叫unlock語句,以確保即使在方法體中丟擲異常(try塊)也會釋放鎖。
            lock.unlock();
        }
    }


    public static void main(String[] args) {
        ReentrantLockService service = new ReentrantLockService();
        for(int i=0; i<100; i++){
            new Thread("" + i){
                @Override
                public void run(){
                    service.getCount();
                }
            }.start();
        }
    }

}

二、Condition
(1)、Condition通過Lock物件呼叫newCondition()方法獲得。藉助Lock,Condition可以實現wait && notify同樣的功能。主要方法:
await(): 使當前執行緒等待
signal():喚醒一個等待的執行緒
signalAll():喚醒所有等待的執行緒
(2)、在使用Condition的方法時需要先獲得鎖,即呼叫Lock物件的lock()方法,否則會丟擲IllegalMonitorStateException,因為沒有監視器物件。

Condition使用例項:

/**
 * @author tangquanbin
 * @date 2018/12/18 21:14
 */
public class ConditionService {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void awaitTest(){
        try {
            lock.lock();
            System.out.println("before await()");
            condition.await();
            System.out.println("after await()");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void signalTest(){
        try {
            lock.lock();
            System.out.println("before signal()");
            condition.signal();
            System.out.println("after signal()");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ConditionService service = new ConditionService();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                service.awaitTest();
            }
        });
        thread1.start();

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                service.signalTest();
            }
        });
        thread2.start();
    }
}