java多線程---重入鎖ReentrantLock

來源:互聯網
上載者:User

標籤:err   重複   art   執行   main   int   取消   使用   print   

1.定義
重入鎖ReentrantLock,支援重入的鎖,表示一個線程對資源的重複加鎖。
2.底層實現
每個鎖關聯一個線程持有人和計數器,當計數器為0時表示該鎖沒有被任何線程持有,那麼任何線程都可能獲得該鎖而調用相應的方法;成功後,JVM會記下鎖的持有線程,並且將計數器置為1;此時其它線程請求該鎖,則必須等待;而該持有鎖的線程如果再次請求這個鎖,就可以再次拿到這個鎖,同時計數器會遞增;當線程退出同步代碼塊時,計數器會遞減,如果計數器為0,則釋放該鎖。
3.使用範例

eg:

import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockTest implements Runnable{    public static int i = 100;    public static ReentrantLock rl = new ReentrantLock();        @Override    public void run() {        while(true){            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            rl.lock();            if(i>0){                System.out.println(Thread.currentThread().getName() + " : " + i--);            }            rl.unlock();        }    }        public static void main(String[] args) {        ReentrantLockTest rlt = new ReentrantLockTest();        Thread t1 = new Thread(rlt);        Thread t2 = new Thread(rlt);        t1.start();        t2.start();    }}

中斷響應
synchronized:線程等待鎖,要麼獲得鎖繼續執行,要麼保持等待。
ReentrantLock:等待鎖的過程中,可以根據需求取消對鎖的請求。
eg:

import java.util.concurrent.locks.ReentrantLock;public class IntLock implements Runnable {    int lock;    public static ReentrantLock lock1 = new ReentrantLock();    public static ReentrantLock lock2 = new ReentrantLock();        public IntLock(int lock){        this.lock = lock;    }            @Override    public void run() {        try{            if(lock == 1){                try{                    lock1.lockInterruptibly();      // 如果當前線程未被中斷,則擷取鎖。                }catch(Exception e){                    e.printStackTrace();                }                lock2.lockInterruptibly();                System.out.println(Thread.currentThread().getId()+"執行完畢");            }else{                lock2.lockInterruptibly();                try{                    Thread.sleep(1000);                }catch(Exception e){                                    }                lock1.lockInterruptibly();            }        }catch(Exception e){            e.printStackTrace();        }finally{            if(lock1.isHeldByCurrentThread()){      //查詢當前線程是否保持此鎖                lock1.unlock();            }            if(lock2.isHeldByCurrentThread()){      //查詢當前線程是否保持此鎖                lock2.unlock();            }            System.out.println(Thread.currentThread().getId()+":線程退出");        }    }        public static void main(String[] args) throws InterruptedException {        IntLock l1 = new IntLock(1);        IntLock l2 = new IntLock(2);        Thread t1 = new Thread(l1);        Thread t2 = new Thread(l2);        t1.start();        t2.start();        Thread.sleep(2000);        t2.interrupt();         //中斷線程,不中斷,則產生死結            }}

鎖申請等待限時
如果鎖在給定等待時間內沒有被另一個線程保持,且當前線程未被中斷,則擷取該鎖。

import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReentrantLock;public class TimeLock implements Runnable {    public static ReentrantLock rl = new ReentrantLock();        @Override    public void run() {        try {            if(rl.tryLock(5, TimeUnit.SECONDS)){                Thread.sleep(6000);                System.out.println(Thread.currentThread().getId()+"執行完畢");            }else{                System.out.println(Thread.currentThread().getId()+"get lock failed");            }        } catch (InterruptedException e) {            e.printStackTrace();        }finally{            if(rl.isHeldByCurrentThread())rl.unlock();        }    }        public static void main(String[] args) {        TimeLock tl = new TimeLock();        Thread t1 = new Thread(tl);        Thread t2 = new Thread(tl);        t1.start();        t2.start();    }}

公平鎖

在ReentrantLock中很明顯可以看到其中同步包括兩種,分別是公平的FairSync和非公平的NonfairSync。公平鎖的作用就是嚴格按照線程啟動的順序來執行的,不允許其他線程插隊執行的;而非公平鎖是允許插隊的。預設情況下ReentrantLock是通過非公平鎖來進行同步的,包括synchronized關鍵字都是如此,因為這樣效能會更好。

public ReentrantLock(boolean fair) //如果此鎖應該使用公平的排序策略,則該參數為 true

import java.util.concurrent.locks.ReentrantLock;public class FairLock implements Runnable{    public static ReentrantLock rl = new ReentrantLock(true);        @Override    public void run() {        while(true){            try {                rl.lock();                System.out.println(Thread.currentThread().getName()+" : get lock");            } catch (Exception e) {            }finally{                rl.unlock();            }        }    }        public static void main(String[] args) {        FairLock fl = new FairLock();        Thread t1 = new Thread(fl,"Thread_One");        Thread t2 = new Thread(fl,"Thread_Two");        t1.start();        t2.start();    }}
在重入鎖的實現中,包含3個要素

1.原子狀態,使用CAS操作來儲存當前鎖的狀態,判斷鎖是否被別的線程持有
2.等待隊列,所有沒有請求到鎖的線程,會進入到隊列進行等待,待有線程釋放鎖後,系統能從等待隊列喚醒一個線程繼續工作。
3.阻塞原語park()和unpark(),用來掛起和恢複線程,沒有得到鎖的線程會被掛起

java多線程---重入鎖ReentrantLock

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.