Lock總結

Lock在咱們平常研發中常常會使用到,好比ReenTrantLock,ReentrantReadWriteLock,StampedLock (JDK1.8新增),java

下面就詳細介紹一下它們的使用方法。bash

  • ReenTrantLock

    ReenTrantLock支持公平鎖和非公平鎖,也是獨佔鎖,下面來講一下ReenTrantLock下的方法和使用。多線程

    1. **lock:**獲取阻塞鎖。ui

      // 默認是費公平鎖,可自定,在參數中增長 true-公平 false-非公平
      ReenTrantLock lockObjcet = new ReenTrantLock();
      try {
        // 獲取鎖 ,若是獲取不到則阻塞線程
        lockObjcet.lock();
        // 同步代碼塊
      } catch (Exception e) {
        
      } finally {
        // 釋放鎖
        lockObjcet.unLock();
      }
      複製代碼
    2. **tryLock:**獲取非阻塞鎖,若是沒法獲取到鎖,返回false,獲取到了返回true。spa

      複製代碼

    ReenTrantLock lock = new ReenTrantLock(); if (lock.tryLock()) { // 獲取到了鎖 } else { // 沒有獲取到鎖 }線程

    3. **tryLock(time):**獲取非阻塞超時鎖,在time時間內若是獲取到了鎖,返回true,獲取不到鎖返回false。
    
    ```java
    ReenTrantLock lock = new ReenTrantLock();
    // 獲取鎖,若是在指定時間內還未得到,則返回false
    if (lock.tryLock(100)) {
      // 獲取到了鎖
    } else {
      // 沒有獲取到鎖
    }
    複製代碼
    1. lockInterruptibly():獲取可中斷鎖,和lock區別就是在獲取鎖的過程當中能夠中斷線程。
    2. **unlock():**解鎖
    3. **boolean isHeldByCurrentThread():**判斷鎖是不是當前線程持有,是返回true,不是返回false。
    4. **boolean isLocked():**判斷鎖是否被獲取或佔用。
    5. **boolean isFair():**是不是公平鎖,是 返回true, 不是返回false。
    6. **Thread getOwner():**獲取當前鎖的擁有者, 若是有擁有者則返回擁有者,若是沒有返回null。
    7. **boolean hasQueuedThreads():**判斷是否有等待線程,若是有則返回true,反之false。
    8. **boolean hasQueuedThread(Thread thread):**判斷入參的線程是否存在於等待隊列中,若是存在則返回true,反之false。
    9. **int getQueueLength():**獲取等待隊列中線程總數。
    10. **Collection getQueuedThreads():**獲取等待隊列中的全部線程。
    11. **boolean hasWaiters(Condition condition):**否有線程在與此鎖關聯的給定條件上等待,有返回true 反之 false。
    12. int getWaitQueueLength(Condition condition):獲取被參數條件等待的線程總數。
    13. **Collection getWaitingThreads(Condition condition):**獲取當前鎖的條件等待的全部線程.
  • ReentrantReadWriteLock

    讀寫鎖: 讀鎖能夠多線程一塊兒獲取,寫鎖只有一個線程能夠獲取,讀寫鎖支持公平鎖和非公平鎖,支持重入鎖。code

    讀鎖: 能夠被多個線程共同獲取鎖,同時進入代碼塊。blog

    寫鎖:只容許一個線程獲取,若是當前線程獲取到寫鎖後,發現有線程獲取了讀鎖,而且不是當前線程,這時當前線程就進入等待狀態。隊列

    代碼示例:ip

    // 讀寫鎖
    private  ReadWriteLock rw = new ReentrantReadWriteLock();
    // 讀鎖 共享鎖
    private  Lock r = rw.readLock();
    // 寫鎖 排它鎖
    private  Lock w = rw.writeLock();
    複製代碼
    • WriteLock
      1. **lock():**寫鎖爲獨佔鎖,當線程A獲取到了寫鎖時任何線程都不能獲取到讀鎖和寫鎖,若是線程A獲取到了寫鎖,可是讀鎖已經被線程B獲取而且未釋放,這時就須要將線程A狀態改成等待,等待線程B釋放了寫鎖再繼續執行。
      2. **unlock():**解鎖。
    • ReadLock
      1. lock(): 加鎖。
      2. unlock(): 解鎖。
  • StampedLock (JDK1.8新增)

    StampedLock: 讀寫鎖,可是StampedLockReenTrantReadWriteLock更塊,可是StampedLock用於樂觀讀鎖,悲觀讀鎖,和寫鎖,StampedLock不支持重入鎖,StampedLock 的悲觀讀鎖、寫鎖都不支持條件變量

    1. **tryOptimisticRead:**樂觀讀。
    2. **readLock:**悲觀讀。
    3. **writeLock:**悲觀寫。

    代碼示例:

    /** * @Auther: lantao * @Date: 2019-05-05 17:55 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    public class StampedLockTest {
    
        static StampedLock s =new StampedLock();
    
        public static void main(String[] args) {
    
            // 悲觀讀
            long l = s.readLock();
    
            // 釋放悲觀讀
            s.unlockRead(l);
    
    
            // 悲觀寫
            long l1 = s.writeLock();
    
            // 釋放悲觀寫
            s.unlockWrite(l1);
    
    
            // 樂觀讀 升級 悲觀讀
            long l2 = s.tryOptimisticRead();
    
            //驗證是否被修改 若是返回false 會釋放 l2,因此後續直接釋放l3便可
            if (!s.validate(l2)){
                // 升級悲觀讀
                long l3 = s.readLock();
                s.unlockRead(l3);
            }
        }
    }
    複製代碼
  • Conditionn

    Condition: Lock 的條件 ,其實初始化的是ConditionObject, ConditionObject是Condition的實現,singal和signlAll的時候須要在獲取鎖後。

    1. await(): 線程等待,至關於**Objcet的wait()**方法。
    2. awaitNanos(time): 等待必定時間,若是超過則繼續執行,至關於Object的wait(time)方法
    3. signal(): 隨機喚醒一個被Condition.await()的線程,至關於Object的notify()方法
    4. signalAll(): 喚醒所有被Condition.await()的線程,至關於Object的notifyAll()方法

    代碼示例:

    /** * @Auther: lantao * @Date: 2019-04-15 14:49 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: Condition 條件 有 singal signalAll 和 await 方法 和Object 的 notify notifyAll 和 wait 是一個意思一樣會釋放鎖 執行singal和notify的時候也須要在等待獲取鎖 */
    public class LockCondition {
    
        public static ReentrantLock lock = new ReentrantLock();
    
        public static Condition a = lock.newCondition();
    
        public static Condition b = lock.newCondition();
    
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable = () -> {
                try {
                    lock.lock();
                    System.out.println(Thread.currentThread().getName());
                    a.await();
    
                    System.out.println(Thread.currentThread().getName() +  " 的 a conndition 被喚醒了");
    
                    b.await();
    
                    System.out.println(Thread.currentThread().getName() +  " 的 b conndition 被喚醒了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            };
    
            Runnable runnable1 = () -> {
                try {
                    lock.lock();
                    System.out.println("線程" +Thread.currentThread().getName() + " 開始執行a condition sinalAll");
                    a.signalAll();
    
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            };
    
            Runnable runnable2 = () -> {
                try {
                    lock.lock();
                    System.out.println("線程" +Thread.currentThread().getName() + " 開始執行b condition sinalAll");
                    b.signalAll();
    
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            };
    
            new Thread(runnable,"Thread1").start();
            new Thread(runnable,"Thread2").start();
            Thread.sleep(100);
            new Thread(runnable1,"Thread3").start();
            Thread.sleep(100);
            new Thread(runnable2,"Thread4").start();
        }
    }
    
    // 執行結果
    Thread1
    Thread2
    線程Thread3 開始執行a condition sinalAll
    Thread1 的 a conndition 被喚醒了
    Thread2 的 a conndition 被喚醒了
    線程Thread4 開始執行b condition sinalAll
    Thread1 的 b conndition 被喚醒了
    Thread2 的 b conndition 被喚醒了
    複製代碼

    博客地址:lantaoblog.site

相關文章
相關標籤/搜索