廖雪峯Java11多線程編程-3高級concurrent包-1ReentrantLock

1.java.util.concurrent

線程同步:java

  • 是由於多線程讀寫競爭資源須要同步
  • Java語言提供了synchronized/wait/notify來實現同步
  • 編寫多線程同步很困難

因此Java提供了更高級的java.util.concurrent包:安全

  • 更高級的同步功能
  • 簡化多線程程序的編寫
  • JDK>= 1.5

2.ReetrantLock

java.util.locks.ReentrantLock用於替代synchronized加鎖 synchronized是Java語言層面提供的,不需考慮異常 ReentrantLock是普通的Java類,要用try...finally來保證鎖可以正確釋放 <img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190612191718983-438603878.png" width="500" /> 當咱們使用ReenTrantLock的時候,咱們首先要經過new ReentrantLock()新建一個Lock對象。而後咱們先試圖用lock()方法得到當前對象的鎖。若是咱們得到鎖成功,就進入try代碼,最後在finally中用unlock()來釋放這個鎖。 <font color="red">注意:lock()方法必須在try代碼以外完成。由於lock()可能會失敗,而unlock()必定要在finally中完成。</font>多線程

class Count{
    final Lock lock = new ReetrantLock(); //得到ReentrantLock對象
    public void inc(){
        lock.lock();    //得到當前對象的鎖可能會失敗,因此要放在try...finally外面
        try{
            n = n + 1;
        }finally{
            lock.unlock(); //釋放鎖
        }
}

ReentrantLock:this

  • 可重入鎖,一個線程可屢次獲取同一個鎖
  • lock()方法可獲取鎖
  • tryLock()方法可嘗試獲取鎖並可指定超時。
class Counter{
    final Lock lock = new ReentrantLock();
    private void inc() throws InterruptedException{
        if(lock.tryLock(1, TimeUnit.SECONDS)){
            try{
                n = n + 1;
            }finally {
                lock.unlock();
            }
        }
    }
}

<font color="blue">使用ReentrantLock比直接使用synchronized更安全,由於synchronized會致使線程要麼得到鎖,要的永遠等待下去。而使用ReentrantLock的時候,咱們經過tryLock()在失敗的時候不會致使死鎖。</font>spa

3.示例

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;

class Counter{
    private Lock lock = new ReentrantLock();
    private int value = 0;
    public void add(int m){
        lock.lock();
        try{
            value += m;
        }finally {
            lock.unlock();
        }
    }
    public void dec(int m){
        lock.lock();
        try{
            value -= m;
        }finally {
            lock.unlock();
        }
    }
    public int get(){
        lock.lock();
        try{
            return this.value;
        }finally {
            lock.unlock();
        }
    }
}
public class Main{
    final static int LOOP = 100;
    public static void main(String[] args) throws Exception{
        Counter counter = new Counter();
        Thread t1 = new Thread(){
            public void run(){
                for(int i=0;i<LOOP;i++){
                    counter.add(1);
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                for(int i=0;i<LOOP;i++){
                    counter.dec(1);
                }
            }
        };
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(counter.get());
    }
}

4.總結:

  • ReentrantLock能夠替代synchronized
  • ReentrantLock獲取鎖更安全
  • lock()獲取鎖在try...finally以前
  • 必須使用try... finally保證釋放鎖
相關文章
相關標籤/搜索