Java高併發26-釋放鎖以及ReentrantLock實例演示

一、釋放鎖

1.void unlock()方法

  • 嘗試釋放鎖,如果當前線程持有鎖,則調用該方法會讓該線程對該線程持有的AQS狀態值減1,如果減去1後當前狀態值爲0,則當前線程會釋放該鎖,否則僅僅減去1而已,如果當前線程沒有持有該鎖而調用了該方法就會拋出IllegalMonitorStateException異常,代碼如下
 public void unlock() {
  sync.release();
 }
 
 public final boolean tryReleaseint releases) {
  // 如果不是鎖持有者,則調用 unlock則拋出異常
  int c = getState() - releases;
  if(Thread.currentThread() != getExclusiveOwnerThread()) {
   throw new IllegalMonitorStateException();
  }
  boolean free = false;
  // 如果當前可重入的次數爲0,則清空鎖持有線程
  if(c == 0) {
   free = true;
   setExclusiveOwnerThread(null);
  }
  // 設置可重入次數爲原始值-1
  setState(c);
  return free;
 }
  • 如上述代碼,如果當前線程不是該鎖的持有者則直接拋出異常,否則查看狀態值是否爲0,爲0則說明當前線程要放棄對該鎖的持有權,則執行代碼把當前鎖的持有者設置爲null,如果狀態值不爲0,則僅僅讓當前線程對該鎖的可重入次數減1.

2.下面以一個案例作爲講解

package com.ruigege.LockSourceAnalysis6;

import java.util.ArrayList;

public static class ReentrantLockList {

 //線程不安全的List
 private ArrayList<String> array = new ArrayList<String>();
 //獨佔鎖
 private volatile ReentrantLock lock = new ReentrantLock();
 
 //添加元素
 public void add(String e) {
  lock.lock();
  try {
   array.add(e);
  }finally {
   lcok.unlock();
  }
 }
 //刪除元素
 public void remove(String e) {
  lock.lock();
  try {
   array.remove(e);
  }finally {
   lock.unlock();
  }
 }
 
 //獲取數據
 public String get(int index) {
  lock.lock();
  try {
   return array.get(index);
  }finally {
   lock.unlock();
  }
 }
}
  • 上述代碼實現了一個線程不安全的array,當一個線程獲取到鎖的時候,進行一系列的增刪改查,如果有其他線程想要獲取到該鎖,那麼就會被放到AQS的隊列中,等待第一個線程釋放鎖,來供它們獲取。

二、讀寫鎖ReentrantReadWriteLock的原理

  • 解決線程安全問題只需要ReentrantLock即可,但是大多數情況下,該鎖是獨佔鎖,某時只有一個線程可以獲取到該鎖,那麼實際上大多情況是寫少讀多,顯然這個場景是無法滿足的。所以ReentrantReadWriteLock就應運而生了,ReentrantReadWriteLock採用的時讀寫分離的策略,可以允許多個線程同時獲取鎖。
  • 我們下次再來解析這個類

三、源碼:

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