淺談多線程

多線程

今天主要想講的是線程安全問題,爲什麼多線程情況下會出現線程不安全問題?

什麼是多線程?

可以簡單的理解爲:即就是一個程序中有多個線程在同時執行。
舉例:我們使用 QQ 音樂同時下載多首音樂時,QQ 音樂程序會創建多個線程來下載音樂。

並行

我們先說下串行。關於串行這個很好理解。假設在單線程情況下,我們使用 QQ 音樂來串行的下載 5 首音樂的話,那下載順序和進度就是 A 下載完成了然後下載 B,順序就是 A-B-C-D-E。

那麼我們來談下並行,在多條線程的情況下,QQ 音樂程序是怎麼完成音樂的下載了?多線程情況下,程序會併發的來執行線程裏的下載音樂的任務,從而會無序的完成 5 首音樂的下載。而不是需要等待 A 下載完成才能下載 B,而是幾乎 "同時" 執行下載的。

關於線程安全

在實際的開發過程中,其實我們寫出的代碼可能存在多線程安全問題。比如:2 條線程同時來對數組進行刪除操作,最後導致程序的 crash。

比如數組 nums = [1,2,3,4,5], 線程 A 獲取 nums 後線程 B 也獲取 nums,然後線程 A 執行 remove(nums[4]), 執行完成後 nums=[1,2,3,4], 然後這個時候 B 也執行執行 remove(nums[4]),導致 crash,因爲數組越界

舉一個簡單的例子來說明下多線程下存在的安全問題: 

現在有一個 Integer 變量,有 2 個線程分別是線程 A 和線程 B 對其進行加 1 操作,如果不設置鎖的話,會造成以下的問題

  1. 開始的時候,線程 A 讀取 integer 變量爲 17,過了一會兒線程 B 也獲取了 integer 變量,此時值也爲 17;

  2. 然後線程 A 執行加 1 操作,此時 integer 值變爲 18;

  3. 又過了一會兒,線程 B 執行加 1 操作,integer 的值還是 18,因爲線程 B 在第一步獲取的變量值爲 17;

  4. 線程 A 和線程 B 將加 1 後的值 18 進行寫入;

  5. 最後,我們發現寫入的值 18 和預期的值 19 不符,所以結果錯誤。

那如何保證線程安全了?

解決方案:使用線程同步技術**(同步,就是協同步調,按預定的先後次序進行)**
常見的線程同步技術是:**加鎖**

如圖所示:

  1. 線程 A 在獲取 integer 變量時,就 lock 加鎖,這個時候其他的線程就不能獲取 integer 變量了

  2. 線程 A 執行加 1 操作,然後寫入完成後,unlock 解鎖,讓別的線程可以訪問 integer 變量
    線程 B 重複上述操作,從而保證了線程的安全。

總結

這是一個非常簡單的多線程模型,在實際的開發過程中,多線程的情況可能會複雜些。例如:多個線程對數組進行刪除操作,如果不保證線程安全的話,最後可能會導致數組越界然後程序 crash;

當然,多線程其實也不難,因爲我們可以使用鎖的機制來處理線程安全問題,那麼你知道一共有多少種鎖嗎,爲什麼會出現不同種類的鎖嗎?

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/A-vZRik1iarSI7QU4Kzl0g