java多線程拾遺(四) 使用ReentrantLock和synchronized來保證線程安全

前言

在多個線程,同時對共享資源進行操作時,會因爲線程不安全,造成數據錯誤。在java中有不同的鎖機制來避免這一問題,除此之外,還有一些線程安全的集合也供我們使用。
在這裏插入圖片描述
可能我們耳熟能詳的是某些集合是線程安全的,某些是線程不安全的。線程安全的集合保證線程安全的方法也不是都一樣的。

今天我們看看如何使用可重入鎖ReentrantLocksynchronized來保證線程安全。

線程不安全的情況

在java中,ArrayList是線程不安全的,我們先模擬一個線程不安全的場景。

/**
 * @author 陽光大男孩!!!
 */
public class CopyOnWriteArrayListTest {
    private static List<Integer> list = new ArrayList<>();

    public  static void add() {
        list.add(1);
    }
    public static void main(String[] args) {

        for (int i = 0; i < 10000; i++) {
            new Thread(() -> add()).start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }

}

在上面的代碼中,我們開啓10000個線程,分別對ArrayList對象進行add操作,爲了讓其執行完,我們讓線程阻塞3s,最後打印ArrayList對象的大小。

看看執行結果

第一次輸出了 9907,第二次輸出了9998,第三次輸出了10000,很顯然這就是一個多線程操作同一個資源導致的線程不安全問題。

使用synchronized關鍵字來保證線程安全

synchronized關鍵字的就是加鎖,通俗來講,就是你在網吧打遊戲,突然想小便,網吧廁所只能容納一個人方便,所以你得等,在廁所裏面的人把門鎖上了,你就進不去。 相當於在廁所裏面的人佔住了資源。

在上例中,多線程操作的是靜態的add方法,所以我們可以對add方法使用synchronized關鍵字來加鎖。

 public  synchronized static void add() {
        list.add(1);
    }

再次運行, 你會發現結果一直都是10000,即正確的,避免了多線程操作同一個資源帶來的線程不安全問題。

使用ReentrantLock鎖來保證線程安全

使用ReentrantLock鎖來保證線程安全也是一樣的,多線程操作的是add方法,所以我們要在add方法中加鎖

 private static final Lock lock = new ReentrantLock();
 
 public static void add() {
 		//加鎖
        lock.lock();
        try {
            list.add(1);
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        finally {
        //釋放鎖
            lock.unlock();
        }
    }

ReentrantLock和synchronized的異同

  1. ReentrantLock是Lock接口的一個實現類,synchronized是一個java 關鍵字
  2. synchronized無法判斷是否獲取到鎖,ReentrantLock可以
  3. synchronized會自動釋放鎖,ReentrantLock需要顯式地手動加鎖和釋放鎖。如果不釋放鎖,可能會出現死鎖問題
  4. 廣義來講, synchronized和ReentrantLock都是可重入鎖,但是synchronized是非公平的、不可以中斷的。 ReentrantLock是一個類,其中有構造方法,可以設置非公平鎖和公平鎖。

總結

保證線程安全的一個有效方法就是互斥同步,互斥是實現同步的一種方法,當達到了同步,也就解決了線程安全的問題。

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