1. 程式人生 > >多執行緒和佇列的通俗理解

多執行緒和佇列的通俗理解

我們先不要用專業的角度來看多執行緒。

先來回憶一下,現實生活中,自己曾經一個人做的事,和多個人同時做的事。

    假如現在某百貨商場做一個搶購活動,限時限量的。那麼就意味著你搶得越多就越佔便宜,至少可以這樣去理解。

    那麼如果你一個人去搶的話,你只有兩隻手,搶得再利害也只有那麼一點,在同等時間的情況下,你的機會會很少的,這也就是我們經常談到的“效率”二字。

    一個人的效率再高,終究是一個人。

    但是你約上親朋好友,一起來搶,那麼你們這個團隊的人,最後搶到的會最多的。

    雖然你會覺得大家平分後可能還是多不了多少,但是你要從另一方面去考慮。

    至少我們這一個團隊的總量比別人多,還有就是大家一起協同作戰,你會覺得開心,效率自然會上去。

    那麼按照總量來看,你一個人會花更多的時間去做這件事,而人數多的情況下,大家相對花的時間就更少。

這就是多執行緒的優勢,所以初步的對多執行緒理解,可以看作是,同時做多件事情,而不是平常我們所想的那樣,一件一件的事情堆著,逐個處理。

有的人就會說,多執行緒哪有你說的這麼簡單啊?

是的,它確實不簡單,但是你如果把所有的問題都看作很複雜的話,等到世界末日那天,你還在想這個問題如何解決呢?

俗話說:大事化小,小事化了。就是告訴你,大問題是由很多小問題組成的,解決一個小問題少一個,遲早會解決掉所有的問題的。

好了,上面已經讓大家瞭解到,多執行緒的基本特徵:併發,同時進行多個事情

下面再來了解一下另一個現象。

現在有3件事情,一件是去市裡買臺電視機,一件事情是去市場買點菜,一件事情是去打掃衛生。

這3件事情同時有3個人去做,但是他們由於事情的複雜度不一樣,路程不一樣,所以回來的時間不一樣。

    但是安排的人並不是坐在這裡等,因為做完了他們會來報告的。

所以這裡就有一個現象:非同步。

所謂非同步,就是指呼叫者不用等待這件事情的完成,而只是讓它開始而已

通俗的解釋就是,安排下去就行了,而不是等到事情的完成,這樣不會浪費安排者的時間。

多執行緒還有一個經常遇到的用法,就是同步。

有時候雖然是安排了一些人去做事情,但是還有一種特殊情況,就是需要同步一些資料。

還是拿剛才那3件事情來舉例,不過這個例子不太恰當,僅作舉例參考用,實際開發的時候是有類似這樣的問題,但現實一般不會有的。

    假如他們3個人完成任務後,都要去櫃檯登記一下,而登記的過程是這樣的,先從印表機那裡列印一張紙,然後填寫自己的名字並提交給祕書,

    這張紙會在上面有一個數字,這個數字是表示你是第幾個回來的。

    那麼按照我們平常的理解,按一下列印,上面的數字會加1對吧。但是假如有這樣一種情況,就是兩個人同時回來的時候,並且同時按下了列印(假設按了兩下),

    那麼這個時候兩個人得到的數字可能是一樣的。

所以這個時候程式上需要處理一個先後順序的問題。

在多執行緒中這個叫鎖,鎖住一個物件,當這個物件被別的執行緒鎖住後,其它的人只能在後面等,直到前面的人用完。這也就是我們常見到的排隊。

總結上面所說,多執行緒有併發、非同步的特性,有同步處理的需求。

什麼情況下用多執行緒?

    1.不需要過問它什麼時候完成,以及不想讓主程式卡住時,就用一個執行緒,讓它慢慢的去執行就行了

    2.有很多事情需要同時進行

    3.特別需要效率的時候,比如多執行緒同時讀取資料,或下載檔案

多執行緒有什麼禁忌?

    1.不是執行緒越多越好,一般建議是CPU核數的2倍為佳,但是也可以多一些;系統的多執行緒總數是有限的,不要無修止的開新執行緒,不然系統資源會很快沒有的

    2.多個執行緒之間需要共用資料的時候,要注意同步的問題(加鎖),經常會死鎖,還有不必要的鎖

    3.在WEB伺服器比如ASP.NET中用多執行緒有時會異常,原因是你在虛擬主機上面使用,而服務端沒有給你過大的資源導致無法分配

    4.在桌面程式(winform)中使用多執行緒時,子執行緒不要直接操作主執行緒的控制元件,不然會莫名的讓程式就退出了

文章的結尾,我介紹一下佇列。

佇列就跟我們排隊買票一樣,這是方便管理人員。在程式中也是方便管理執行緒。

正在排隊的人就是等待要做的事情,服務視窗就是執行緒。

所以佇列就是一個管理器,它管理同時進行的執行緒數,以免執行緒過多,導致效率低下,甚至系統崩潰。

    它的主要用處就是跟售票視窗一樣,當一個人辦完手續後,這個人就走了,就意味著有一個視窗處於空閒狀態,所以這個時候後面排隊的可以去一個人繼續辦理。

    那麼多執行緒也一樣,當然不需要每個視窗都排隊,都排在一個列表裡面,當某個執行緒完成時,必須想辦法通知佇列,說我已經完成了。這個時候佇列就知道已經少了一個執行緒在做事了,就會開一個新的執行緒去做下一件事情,這樣讓同時進行的執行緒數總是維持在一個特定的數內。