多線程基礎知識瞭解一下

(一) 前言

做爲一名優秀的攻城師,瞭解多線程的知識很是有必要,尤爲在人工智能和機器學習的熱潮下,如何提升程序或者算法的運行效率是很是有價值的一件事情。html

在當代大多數的操做系統,都有能力同時的運行多個程序或者app,好比在windows上你能夠同時打開多個QQ,多個不一樣的瀏覽器,多個不一樣的視頻播放器。或者在你的蘋果或者安卓手機上邊聽歌邊使用地圖功能,這背後其實用的就是用的是多線程的技術。java

image

(二)多任務處理

在同一時刻運行多個程序也叫作多任務處理,每一個程序會由一個單獨的task來執行,每一個task運行在一個單獨的處理器中(能夠理解爲是一個進程或者一個CPU)。在早期的計算機操做系統中,每每都是單處理器的,這時候你也能同時運行多個程序,這種狀況咱們稱爲併發而不是並行,由於這個時候多個程序實際上是共用的一個CPU時鐘,因爲計算機的時間片切換很是快,因此大多數時候你是感受不到這種差別的,但實際上是一種假象。隨着社會的進步,如今的電腦基本上都是多個CPU的,因此在多個CPU的狀況下,程序纔可以真正的並行起來。算法

(三)線程與多線程

每一個處理器能夠建立多個子任務,這裏的每個子任務都是一個線程。一個線程執行的其實就是一段代碼指令序列。在一個處理器內的多個線程是能夠經過處理器的共享內存進行交互的,關鍵詞併發(concurrency)指的就是在一個處理器內同時執行多個線程。編程

多線程一般是經過把大的任務切分紅多個子任務運行,以此來提升程序運行效率的。比較典型的例子就是現實中修一段高速公路時,最快的方法就是,把這條公路切分紅多段,而後每一個段由一個工程隊負責,這樣同時工做就能大大提升效率。windows

(四)併發與線程上下文切換

上面說過,單個處理器內的多線程任務實際上是一種假象,實際上是經過切換CPU時鐘實現的,這個時候,在切到另外一個線程以前,CPU必須保存當前線程的狀態,這被稱爲上下文切換,這也是單核處理器能同時執行多個任務的祕密。瀏覽器

線程切換是一個比較昂貴的操做,調度器須要花費額外的CPU時間來臨時暫停當前活躍的線程爲了讓另一個線程運行,而後保存當前線程狀態,在須要的時候,還得恢復當前掛起的線程狀態。緩存

image

(五)線程調度

線程調度主要負責線程的上下文切換,它決定了接下來要選擇哪一個掛起的線程執行。線程調度是操做系統的一部分。安全

(六)互斥

互斥的目的是保證在兩個線程之間不能同時執行同一個代碼片斷。通俗點來講就是咱們在大街上看到的紅綠燈,任什麼時候候只能有一種顏色的燈在亮。 互斥的資源一般是須要被共享的,好比衛生間的馬桶,任什麼時候候只能有一我的用,若是同時有多我的用那麼就會出現問題,這也叫競爭,反映到程序中,多是一種數據解構,一個外部設備如打印機,或者一個網絡鏈接。網絡

競爭一般會帶來問題,因此在程序中一般使用鎖機制(lock)來達到互斥的目的,互斥也能夠稱爲線程同步(synchronization)多線程

同步帶來的缺點是,在一個線程沒有釋放鎖以前,另一個線程須要一直等待。它強制調度是串行操做的,即便這裏有多個空閒的CPU資源,因此在平常開發中要合理使用。

(七)併發與並行

並行:

並行指的是多線程運行在不一樣的CPU或者處理器上,從而避免了在同一個CPU或者處理器中的上下文切換的操做。固然這裏是多個線程之間不須要通訊或者有共享資源須要訪問。這種狀況就能夠獨立的執行和計算。固然前提是硬件有多個CPU或者處理器。

併發:

併發指的是多個線程有通訊或者須要訪問共享的數據,這個時候須要考慮加鎖,不然有可能安全問題。一般狀況下併發是指運行在同一個CPU或者core內,但這並非十分準確,多個線程也能夠運行在多個CPU內可是他們有合理的同步策略。

image

(八)多處理器 vs 多core vs 超線程

多處理器是指在單臺電腦上有多個CPU單元,每個處理器能夠有多個core,每一個core能夠運行一個任務,多線程程序每一個線程均可以並行的運行在一個core中。

注意單個core也有可能運行兩個並行的線程,這種能力被稱爲超線程。

超線程(HT, Hyper-Threading)[1]是英特爾研發的一種技術,於2002年發佈。超線程技術原先只應用於Xeon 處理器中,當時稱爲「Super-Threading」。以後陸續應用在Pentium 4 HT中。早期代號爲Jackson。 <br/> 經過此技術,英特爾實如今一個實體CPU中,提供兩個邏輯線程。以後的Pentium D縱使不支持超線程技術,但就集成了兩個實體核心,因此仍會見到兩個線程。超線程的將來發展,是提高處理器的邏輯線程。英特爾於2016年發佈的Core i7-6950X即是將10核心的處理器,加上超線程技術,使之成爲20個邏輯線程的產品。

超線程實際上是一個CPU單元內,提供了兩個邏輯線程,依賴於底層操做系統,若是操做系統不支持,也能夠禁用掉。所以在一個4 core 處理器系統中可能有8個邏輯處理器。

(九)線程 與 CPU緩存

依賴於CPU的類型,當前的操做系統基本都支持三級緩存,CPU緩存的目的是爲了CPU訪問CPU緩存數據更快,這種快是相對於CPU讀取內存數據而言(RAM),一般狀況下通常高出幾個數量級。

L1 級別緩存 在cpu的芯片中,體積通常是8-64kb

L2 級別緩存 一般位於CPU和RAM之間,體積通常是2-4MB

L3 級別緩存 若是存在通常都位於主板上,體積通常是8-16MB (注:跟CPU類型有關,一些CPU類型可能直接用L2替代L3了)

image

下面經過表格看下不一樣的介質,訪問的耗時狀況,其中L1緩存屬於core級別的,因此每一個運行在core裏面的線程均可以擁有本身的local cache。

從CPU到 大約須要的CPU週期 大約須要的時間(單位ns)
寄存器 1 cycle 能夠忽略
L1 Cache ~3-4 cycles ~0.5-1 ns
L2 Cache ~3-4 cycles ~0.5-1 ns
L3 Cache ~3-4 cycles ~0.5-1 ns
跨槽 ~30-40 cycles ~20 ns
內存 ~120-240 cycles ~60-120ns

(十) 總結

本篇主要介紹了多線程有關的一些基礎概念以及CPU的cache模型,在一個多線程的程序中,爲了提升處理性能,每一個線程都有本身的CPU緩存,而同時若是多個線程想要訪問一塊共享的區域(位於主內存中),須要考慮同步和可見性的問題,,因此一些編程語言如C,C++,C#和Java都會有確保變量在修改以後對其餘線程可見的語義,如Java裏面的volatile關鍵詞會強制flush線程的local cache的數據到主存中,除此以外一些鎖機制也會觸發,如lock和unlock指令,這些知識點會在後面的文章中一一介紹。

參考文章:

https://www.logicbig.com/quick-info/programming/multi-threading.html#processor-cache

https://medium.com/@bkodirov/threading-in-java-55ec2e184fe7

image

相關文章
相關標籤/搜索