4.1 顯示鎖ReentrantLock的理解,使用示例

目錄

有了synchronized爲什麼還要Lock

lock常用的方法

lock使用的標準代碼

ReentrantLock使用示例lock和unlock:

ReentrantLock使用示例tryLock()

ReentrantLock使用示例lock.lockInterruptibly();


有了synchronized爲什麼還要Lock

  Synchronized ReentrantLock
類型 關鍵字:修飾方法或者代碼塊 接口:常用的五個方法
  隱式獲取鎖,把鎖的獲取和釋放固化了,即先獲取再釋放

1、能夠嘗試非阻塞獲取鎖(tryLock())

2、能夠響應中斷,被中斷時,會跑出中斷異常,同時會釋放鎖

3、能夠超時獲取鎖tryLock(long time, TimeUnit unit)

可重入(原理:線程持有者和計數器) 支持 已經獲取到鎖的線程,能夠再次調用lock()方法獲取鎖而不被阻塞

公平:先對鎖獲取的先被滿足,效率低

非公平:多個線程不管先後競爭鎖

非公平 通過構造函數自定義public ReentrantLock(boolean fair)

 

lock常用的方法

方法名稱 描述
void lock(); 獲取鎖,調用該方法當前線程會獲取鎖,當獲取鎖後,從該方法返回
void lockInterruptibly() throws InterruptedException; 可中斷地獲取鎖,和lock()方法的不同之處在於該方法會響應中斷,即在鎖的獲取中可以中斷當前線程
boolean tryLock(); 嘗試獲取鎖,調用後回立即返回,獲取到鎖true,否則返回fasle
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

1、在超時時間獲取鎖:true

2、在超時時間內被中斷:false

3、超時:false

void unlock(); 釋放鎖

lock使用的標準代碼

lock.lock();
try{
    count++;    
}finally{
    lock.unLock();
}

ReentrantLock使用示例lock和unlock:

兩個線程對count自增1000,另一個線程對count自減1000

public class MyReentrantLock {
    int count = 1000;

    public static void main(String[] args) throws InterruptedException {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        Lock lock = new ReentrantLock();
        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                lock.lock();
                try {
                    myReentrantLock.count++;
                } finally {
                    lock.unlock();
                }
            }
        }).start();
        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                lock.lock();
                try {
                    myReentrantLock.count--;
                } finally {
                    lock.unlock();
                }
            }
        }).start();
        //主線程一定要進行休眠,否則可能會得到修改過程中count的值,而不是最終值
        Thread.sleep(1000);
        System.out.println(myReentrantLock.count);
    }
}

結果:1000

ReentrantLock使用示例tryLock()

public static void main(String[] args) throws InterruptedException {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        Lock lock = new ReentrantLock();
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {

                        Thread.sleep(100);
                        myReentrantLock.count++;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        });
        thread.start();
        //thread.interrupt();


        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                if (lock.tryLock()) {
                    try {
                        myReentrantLock.count--;
                    } finally {
                        lock.unlock();
                    }
                }

            }
        });
        //thread2.interrupt();
        //主線程一定要進行休眠,否則可能會得到修改過程中count的值,而不是最終值
        Thread.sleep(1000);
        System.out.println(myReentrantLock.count);
    }
}

結果在:1000-1010之間

ReentrantLock使用示例lock.lockInterruptibly();

public class MyReentrantLock {
    int count = 1000;

    public static void main(String[] args) throws InterruptedException {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        Lock lock = new ReentrantLock();

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    lock.lockInterruptibly();
                    Thread.sleep(100);
                    myReentrantLock.count--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }

        });
        thread2.start();
        Thread.sleep(100);
        thread2.interrupt();
        //主線程一定要進行休眠,否則可能會得到修改過程中count的值,而不是最終值
        Thread.sleep(1200);
        System.out.println(myReentrantLock.count);
    }
}

結果:

java.lang.InterruptedException
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
	at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
	at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:39)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
	at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
	at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:45)
	at java.lang.Thread.run(Thread.java:748)
999

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章