1. 程式人生 > >JDK併發包--重入鎖

JDK併發包--重入鎖

重入鎖基本使用:
    使用java.util.concurrent.locks.ReentrantLock 類來實現,可以替代synchronized關鍵字。如下例,重入鎖有著顯示的操作過程,開發者可以手動指定在哪裡加鎖,在哪裡釋放(退出臨界區時必須釋放,不然其他執行緒沒有機會再訪問了)。重入的意思是,同一個執行緒可以多次獲得鎖,同樣的退出時需要多次釋放。
    public class LockDemo implements Runnable{
        public static ReentrantLock lock = new ReentrantLock();
        public static int i=0;
        public finnal int N= 10000;
        @Override
        public void run(){
            for(int j=0;j<N;j++){
                lock.lock();    //加鎖
                lock.lock();
                try(
                    i++;
                )finally{
                    lock.unlock();    //釋放鎖
                    lock.unlock();
                }
            }
        }
        public static void main(String[] args){
            LockDemo tLock = new LockDemo();
            Thread t1 = new Thread(tLock);
            Thread t2 = new Thread(tLock);
            t1.start();t2.start();
            t1.join();t2.join();
            System.out.println(i);//最終輸出20000
        }
    }

中斷響應:


    對鎖的請求使用lockInterruptibly()方法,可以在等待鎖的過程中響應中斷
    package com.test;
    import java.util.concurrent.locks.ReentrantLock;

    public class IntruptLock implements Runnable{
        public static ReentrantLock lock1 = new ReentrantLock();
        public static ReentrantLock lock2 = new ReentrantLock();
        int lock;//控制加鎖順序,方便構成死鎖
        public IntruptLock(int lock){this.lock = lock;}
        public void run(){
            try{
                if(lock==1){
                    while(true){
                        lock1.lockInterruptibly();
                        try{
                            Thread.sleep(1000);
                        }catch(InterruptedException e) {
                        
                        }
                        lock2.lockInterruptibly();    
                    }
                }else {
                    while(true){
                        lock2.lockInterruptibly();
                        try {
                            Thread.sleep(1000);
                        }catch(InterruptedException e) {
                            lock1.lockInterruptibly();
                        }
                    }
                }
            }catch(InterruptedException e){
                e.printStackTrace();
            }finally{
                if(lock1.isHeldByCurrentThread()) {
                    lock1.unlock();
                }
                if(lock2.isHeldByCurrentThread()) {
                    lock2.unlock();
                }
                System.out.println(Thread.currentThread().getName()+":執行緒退出");
            }
        }
        public static void main(String[] args) throws InterruptedException {
            IntruptLock r1 = new IntruptLock(1);
            IntruptLock r2 = new IntruptLock(2);
            //t1先獲得lock1鎖,再申請lock2,t2先獲得lock2鎖,再申請lock1,構成死鎖

            Thread t1 = new Thread(r1);
            Thread t2 = new Thread(r2);
            t1.start();
            t2.start();
            Thread.sleep(1000);
            t2.interrupt();//中斷t2,lock2響應中斷,t2釋放lock2鎖,t1得以執行下去

        }
    }

tryLock():
    仍然是上個栗子,如果使用的是tryLock(),t2在申請lock1時沒有獲得,它不會傻傻的等,而是會立刻返回false,然後繼續執行重新嘗試,只要時間夠長,總會獲得lock1而執行下去。
    tryLock()也可以傳入引數,tryLock(10,TimeUnit.SECONDS),分別表示時長和時間單位。

公平鎖:
    public ReentrantLock(boolean fair),各執行緒獲得公平鎖的概率是相等的。