多线程基础知识了解一下
2019獨角獸企業重金招聘Python工程師標準>>>
(一) 前言
作為一名優秀的攻城師,了解多線程的知識非常有必要,尤其在人工智能和機器學習的熱潮下,如何提高程序或者算法的運行效率是非常有價值的一件事情。
在當代大多數的操作系統,都有能力同時的運行多個程序或者app,比如在windows上你可以同時打開多個QQ,多個不同的瀏覽器,多個不同的視頻播放器。或者在你的蘋果或者安卓手機上邊聽歌邊使用地圖功能,這背后其實用的就是用的是多線程的技術。
(二)多任務處理
在同一時刻運行多個程序也叫做多任務處理,每個程序會由一個單獨的task來執行,每個task運行在一個單獨的處理器中(可以理解為是一個進程或者一個CPU)。在早期的計算機操作系統中,往往都是單處理器的,這時候你也能同時運行多個程序,這種情況我們稱為并發而不是并行,因為這個時候多個程序其實是共用的一個CPU時鐘,由于計算機的時間片切換非常快,所以大多數時候你是感覺不到這種差異的,但其實是一種假象。隨著社會的進步,現在的電腦基本上都是多個CPU的,所以在多個CPU的情況下,程序才能夠真正的并行起來。
(三)線程與多線程
每個處理器可以創建多個子任務,這里的每一個子任務都是一個線程。一個線程執行的其實就是一段代碼指令序列。在一個處理器內的多個線程是可以通過處理器的共享內存進行交互的,關鍵詞并發(concurrency)指的就是在一個處理器內同時執行多個線程。
多線程通常是通過把大的任務切分成多個子任務運行,以此來提高程序運行效率的。比較典型的例子就是現實中修一段高速公路時,最快的方法就是,把這條公路切分成多段,然后每個段由一個工程隊負責,這樣同時工作就能大大提高效率。
(四)并發與線程上下文切換
上面說過,單個處理器內的多線程任務其實是一種假象,其實是通過切換CPU時鐘實現的,這個時候,在切到另一個線程之前,CPU必須保存當前線程的狀態,這被稱為上下文切換,這也是單核處理器能同時執行多個任務的秘密。
線程切換是一個比較昂貴的操作,調度器需要花費額外的CPU時間來臨時暫停當前活躍的線程為了讓另外一個線程運行,然后保存當前線程狀態,在需要的時候,還得恢復當前掛起的線程狀態。
(五)線程調度
線程調度主要負責線程的上下文切換,它決定了接下來要選擇哪個掛起的線程執行。線程調度是操作系統的一部分。
(六)互斥
互斥的目的是保證在兩個線程之間不能同時執行同一個代碼片段。通俗點來說就是我們在大街上看到的紅綠燈,任何時候只能有一種顏色的燈在亮。 互斥的資源通常是需要被共享的,比如衛生間的馬桶,任何時候只能有一個人用,如果同時有多個人用那么就會出現問題,這也叫競爭,反映到程序中,可能是一種數據解構,一個外部設備如打印機,或者一個網絡連接。
競爭通常會帶來問題,所以在程序中通常使用鎖機制(lock)來達到互斥的目的,互斥也可以稱為線程同步(synchronization)
同步帶來的缺點是,在一個線程沒有釋放鎖之前,另外一個線程需要一直等待。它強制調度是串行操作的,即使這里有多個空閑的CPU資源,所以在日常開發中要合理使用。
(七)并發與并行
并行:
并行指的是多線程運行在不同的CPU或者處理器上,從而避免了在同一個CPU或者處理器中的上下文切換的操作。當然這里是多個線程之間不需要通信或者有共享資源需要訪問。這種情況就可以獨立的執行和計算。當然前提是硬件有多個CPU或者處理器。
并發:
并發指的是多個線程有通信或者需要訪問共享的數據,這個時候需要考慮加鎖,否則有可能安全問題。通常情況下并發是指運行在同一個CPU或者core內,但這并不是十分準確,多個線程也可以運行在多個CPU內但是他們有合理的同步策略。
(八)多處理器 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了)
下面通過表格看下不同的介質,訪問的耗時情況,其中L1緩存屬于core級別的,所以每個運行在core里面的線程都可以擁有自己的local cache。
| 寄存器 | 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
轉載于:https://my.oschina.net/u/1027043/blog/1831158
總結
以上是生活随笔為你收集整理的多线程基础知识了解一下的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Azure系列2.1.13 —— Clo
- 下一篇: python基础之----函数
