多線程基本概念
同步和異步
◆
同步就好比打電話,通信雙方,你一句我一句,一句話得不到回應就會一直問:“餵?餵?可以聽到麽?是不是信號不好呀”。
異步就像發短信,發完短信我就去幹點別的,看個視頻、玩個遊戲、幹啥都行,等對方給我回信息了我再來處理短信(也可以不處理)。
◆
線程和進程
◆
進程的概念聽起來很抽象,不大好理解。但是我知道你肯定認識這個東西,請看下圖:
上方這些占用我的電腦CPU、內存、磁盤、網絡的這些就都是進程。
那什麽是線程呢?線程可以理解成是在進程中獨立運行的子任務。比如微信運行時就會有很多的子任務在同時運行。比如,視頻線程、下載線程、表情線程、語言線程等。簡單來說,一組線程互相協作完成某一個程序的一些功能供我們使用。
◆
並發和並行
◆
並發和並行乍一看好像是一種東西,但是實際上區別很大。並發表示的是交替做不同事情的能力,而並行表示的是同時做不同事情的能力。例如你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這就是並發。你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這是並行。
我們常說的高並發系統就是說的並發而不是並行。
並不是所有的系統都可以實現並行,因為一個CPU一次只能執行一條指令,所以想要實現並行必須是多核才可以
◆
臨界資源
◆
臨界資源:是一次僅允許一個進程使用的共享資源。例如公共電話,一次只能一個人使用
臨界區:每個進程中訪問臨界資源的那段代碼叫做臨界區。例如使用公共電話的人
◆
阻塞
◆
線程在試圖執行代碼前,會試圖獲取臨界區的鎖,如果得不到,線程就會被掛起等待,從而形成阻塞。
◆
死鎖
◆
多個線程循環等待它方占有的資源而無限期地僵持下去的局面。例如兩個人想要使用公共電話打電話,結果一個人搶到了話筒,一個人撥了號。兩個人誰也不讓誰,就會無休止地等下去從而引起死鎖。
死鎖產生的四大必要因素:
互斥:某種資源一次只允許一個進程訪問,即該資源一旦分配給某個進程,其他進程就不能再訪問,直到該進程訪問結束。 占有且等待:一個進程本身占有部分資源,同時還有資源未得到滿足,正在等待其他進程釋放該資源。 不可搶占:別人已經占有了某項資源,你不能因為自己也需要該資源,就去把別人的資源搶過來。 循環等待:存在一個進程鏈,使得每個進程都占有下一個進程所需的至少一種資源。
當以上四個條件都滿足時才會發生死鎖,所以想要避免死鎖只要能破壞上方四個條件的任意一個都可以。
◆
饑餓
◆
線程因為優先級或其他原因始終無法獲取到臨界資源。例如A在使用公用電話在打電話,B來了之後在後面排隊。之後C來了,一看認識A,好麽,哥們你打完我來。然後D來了,他認識C。。。就這樣B一直等待從而引起饑餓。
◆
活鎖
◆
多個相互協作的線程為了彼此間的響應而相互禮讓,使得沒有一個線程能夠繼續前進,那麽就發生了活鎖。例如兩個人在一個很宅的胡同裏。一次只能並排過兩個人。兩人比較禮貌,都要給對方讓路。 結果一起要麽讓到左邊,要麽讓到右邊,結果仍然是誰也過不去從而引起的活鎖。
◆
線程的並發級別
◆
阻塞:參見上方阻塞的定義
無饑餓:對比上方的饑餓,如果設置所有線程的優先級相同,則任何想要獲取資源的線程都要排隊,那麽所有的線程都有機會執行。
無阻塞:所有線程一起修改臨界資源,修改完成後讀取該資源是否被其他線程修改,如被其他線程修改則進行回滾,然後進行重試。
無鎖:前面說的無阻塞是指所有的線程都能進入臨界區,但如果發生了競爭,線程發現自己的數據每次去操作總是跟其它線程產生沖突,它就會不停地重試,如果在臨界區當中有10個線程,線程1修改了部分數據,結果它被線程2幹擾了,線程2又被線程3幹擾,依此類推,最後線程1它又可能去幹擾線程10,如果它們之間是彼此幹擾的,最終會導致所有的線程都卡死在裏面。而無鎖在無阻塞的基礎上加一個了約束,保證在競爭當中有一個線程是必然能夠勝出的,這樣就能保證在臨界區的線程當中至少有一個是能順利走出去的。當第一個線程走出去之後,就有第二個線程、第三個線程、等所有的線程都能走出去
無等待:無等待相比於無鎖更進一步,它保證所有線程能進並且至少有一個線程能出來的同時還要求所有進入臨界區的線程都能夠在有限步當中完成其操作。
![](https://s1.51cto.com/images/blog/201903/20/73981b702637842b9b333bd9efeb8225.jpg?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
多線程基本概念