1、多線程簡單介紹

概述

多線程,顧名思義也就是說多個線程共同執行來保證應用的穩定性和可用性,現如今幾乎所有的應用都採用多線程模式。JAVA 語言從一開始就支持多線程,並通過併發包(java.util.concurrent)封裝了一系列和線程有關的JAVA類。作爲開發者,我們在使用這些併發包的時候也應該清楚其中的原理,這樣以後在遇到問題時也可以儘快找出原因。


多線程

本篇我們主要通過以下三個模塊簡單的介紹多線程:

  1. 多線程的發展史
  2. 多線程帶來的挑戰
  3. 併發和並行

1、多線程的發展史

在最開始的單CPU時代,單時間點只能執行單任務。也就是說,那個時候大多數任務採用單線程執行,並且同一時刻只能有一個任務執行。

之後發展到多任務執行時代,計算機可以在同一時間點“同時”執行多個任務。這裏的“同時”不是說同一時間點執行,而是說多個任務共享一塊CPU,並通過操作系統來完成多任務在CPU上的運行切換,保證每個任務都能獲得一定的執行時間。

再後來發展到多線程時代,一個程序內部不再單單僅有一個線程,而是很多線程共同運行的結果。程序中每個線程的執行都可以理解爲CPU在執行該線程,就好像有多個CPU在同時執行該程序。


2、多線程帶來的挑戰

多線程相比多任務更加有挑戰。

在多任務的場景下,每個任務有自己獨立的內存空間,各個任務之間互不影響,即使各個任務之間交替執行,也極少產生線程安全性問題。

但在多線程場景下,各個任務共享一塊內存空間,極有可能產生多個線程同時操作同一塊內存區域的場景,在這種場景下,極有可能產生 線程安全問題

假設一個程序中某個線程在讀取一塊內存時,另一個線程正在往這塊內存寫新值,那麼該線程讀取到的值是什麼?是老值還是新寫入的值?還是說一半老值一半新值?

還有一種更常見的案例:現在有兩個線程同時往一塊內存寫值,那麼最終寫入的值是線程一的值 還是說 線程二的值,還是說其他值。通過這兩個案例,我們會發現多線程場景下,如果我們不做保證線程安全的操作下,其所產生的結果是無法預料的。

而且線程的交替執行沒有規律,如果出現線程安全問題很難復現其過程。因此最好的方法就是在程序運行前通過一系列操作保證線程的安全,這也正是多線程所帶來的挑戰。


3、並行和併發

上面我們所舉的例子主要圍繞單核CPU的場景展開,即所有線程根據操作系統調度切換,並保證每個線程都有分配到CPU的機會,這種單核CPU下,多線程同時執行的方式我們稱之爲“併發

目前市面上計算機技術已經相當成熟,很多計算機都是多處理器。在多核CPU的場景下,是可以做到真正意義上的多個任務同時執行,這種多核CPU下,多線程同時執行的方式我們稱之爲“並行

舉個不太恰當的例子:公司每天早上班,員工需要通過正門進入公司辦公。

併發就是公司只有一個門,很多員工都在執行“進門”操作,但是同時只能有一名員工進門,其他員工只能在後面等着,等到門空出來後,執行進門操作。

並行就是公司有兩個或多個門,同時可以有多個員工通過不同的門進入公司,也就是說,多個員工在同一時刻執行進門操作。

問題:雖然看例子這兩種情況存在天壤之別,但是用戶爲什麼一般看不出來呢?

這其實是因爲無論單核CPU 還是 多核CPU,操作系統都營造出了多個任務在同時執行的假象。實際的過程是通過操作系統對進線的調度以及CPU的高速上下文切換完成的每個進程執行一會就先停下來,然後CPU切換到下個被操作系統調度到的進程上使之運行。因爲切換的很快,使得用戶認爲操作系統一直在服務自己的程序。

有了上面的鋪墊,我們再帶出“串行”的概念。還是上面排隊上班這個例子。

串行就是說,所有員工按照某種規則依次排隊進入大樓,這是一種很典型的單CPU單線程模型,即按照某個規則,依次執行某些操作。

最後我們需要注意的一點是:並行是程序員無法控制的,而是是由操作系統決定的。我們需要注重是在併發場景下,保證“線程安全性”問題。並行與否與CPU的個數,CPU的調度次數無關,操作系統的調度系統會盡量讓不同進程/線程使用不同的CPU核心,所以在實際使用中幾乎總是會並行。


參考:
https://www.cnblogs.com/f-ck-need-u/p/11161481.html
https://blog.csdn.net/likun557/article/details/53319697
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章