定義
在計算機編程中,一個基本的概念就是同時對多個
任務加以控制。許多
程式設計問題都要求程式能夠停下手
頭的工作,改為處理其他一些問題,再返回主
進程。可以通過多種途徑達到這個目的。最開始的時候,那些掌握機器低級語言的
程式設計師編寫一些“中斷服務例程”,主
進程的暫停是通過
硬體級的中斷實現的。儘管這是一種有用的方法,但編出的
程式很難移植,由此造成了另一類的代價高昂問題。中斷對那些實時性很強的
任務來說是很有必要的。但對於其他許多問題,只要求將問題劃分進入獨立運行的
程式片斷中,使整個程式能更迅速地回響用戶的請求。
最開始,執行緒只是用於分配單個處理器的處理時間的一種工具。但假如
作業系統本身支持多個處理器,那么每個執行緒都可分配給一個不同的處理器,真正進入“並行運算”狀態。從
程式設計語言的角度看,多執行緒操作最有價值的特性之一就是
程式設計師不必關心到底使用了多少個處理器。
程式在邏輯意義上被分割為數個執行緒;假如機器本身安裝了多個處理器,那么程式會運行得更快,毋需作出任何特殊的調校。根據前面的論述,大家可能感覺執行緒處理非常簡單。但必須注意一個問題:共享資源!如果有多個執行緒同時運行,而且它們試圖訪問相同的資源,就會遇到一個問題。舉個例子來說,兩個執行緒不能將信息同時傳送給一台
印表機。為解決這個問題,對那些可共享的資源來說(比如
印表機),它們在使用期間必須進入鎖定狀態。所以一個執行緒可將資源鎖定,在完成了它的
任務後,再解開(釋放)這個鎖,使其他執行緒可以接著使用同樣的資源。
多執行緒是為了同步完成多項
任務,不是為了提高運行效率,而是為了提高
資源使用效率來提高系統的效率。執行緒是在同一時間需要完成多項
任務的時候實現的。
最簡單的比喻多執行緒就像火車的每一節
車廂,而進程則是火車。車廂離開
火車是無法跑動的,同理火車也不可能只有一節車廂。多執行緒的出現就是為了提高效率。同時它的出現也帶來了一些問題。
用途
在大多數研究領域內是要求執行緒調度程式要能夠快速選擇其中一個已就緒執行緒去運行,而不是一個一個運行而降低效率。所以要讓調度程式去分辨執行緒的優先權是很重要的。而執行緒調度程式可能是以硬體、軟體,或是軟硬體並存的形式存在。
而另一個研究領域則是要研究何種事件(高速快取失敗、內部運行連續性、使用DMA等)會造成執行緒切換。
如果多執行緒的方案會複製
所有軟體可見的狀態,包括特許的控制登錄、TLB 等,那就能夠讓
虛擬機去創造各式執行緒。這樣子就允許在相同的處理器中每個執行緒跑各自的作業系統。換句話說,如果只有存儲了用戶模式的狀態,就能夠讓相同的裸晶大小的晶片在一段時間內處理更多的執行緒。
硬體支持
多執行緒硬體支持的目標,即支持快速進行就緒態執行緒、執行態執行緒間的切換。為達成這個目標,需要硬體實現保存、恢復程式看得見的暫存器以及一些對程式執行有影響的控制暫存器(如程式計數器PC、程式狀態暫存器SR)。從一個執行緒切換到另一個執行緒對硬體來講意味著保存當前執行緒的一組暫存器的值,並恢復即將執行執行緒的一組暫存器的值。
新增這些功能的硬體有以下優勢:
為了在各個執行緒間有效率的進行切換,每個執行緒需要保存自己的一組暫存器集(register set)。有些硬體設計成每個處理器核心具有兩組暫存器檔案,以實現在多個執行緒間快速切換。
執行緒
定義
英文:Thread
每個正在系統上運行的
程式都是一個
進程。每個
進程包含一到多個執行緒。
進程也可能是整個
程式或者是部分程式的動態執行。執行緒是一組
指令的集合,或者是
程式的特殊段,它可以在程式里獨立執行。也可以把它理解為
代碼運行的上下文。所以執行緒基本上是輕量級的
進程,它負責在單個
程式里執行多
任務。通常由
作業系統負責多個執行緒的調度和執行。
執行緒是
程式中一個單一的順序控制流程.在單個程式中同時運行多個執行緒完成不同的工作,稱為多執行緒.
執行緒和
進程的區別在於,子進程和
父進程有不同的
代碼和數據空間,而多個執行緒則共享數據空間,每個執行緒有自己的執行
堆疊和
程式計數器為其執行上下文.多執行緒主要是為了節約CPU時間,發揮利用,根據具體
情況而定. 執行緒的運行中需要使用計算機的
記憶體資源和CPU。
優點
·用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度
·在一些等待的
任務實現上如用戶輸入、檔案讀寫和網路收發數據等,執行緒就比較有用了。在這種
情況下可以釋放一些珍貴的資源如
記憶體占用等等。
.多執行緒技術在IOS軟體開發中也有舉足輕重的位置。
.執行緒套用的好處還有很多,就不一一說明了
缺點
·如果有大量的執行緒,會影響性能,因為
作業系統需要在它們之間切換。
·執行緒可能會給
程式帶來更多“bug”,因此要小心使用。
·通常塊模型數據是在多個執行緒間共享的,需要防止執行緒死鎖
情況的發生。
一些執行緒模型的背景
可以重點討論一下在
Win32環境中常用的一些模型。
·單執行緒模型
在這種執行緒模型中,一個
進程中只能有一個執行緒,剩下的進程必須等待當前的執行緒執行完。這種模型的缺點在於系統完成一個很小的
任務都必須占用很長的時間。
這種模型里,一個
程式里可能會包含多個執行的執行緒。在這裡,每個執行緒被分為
進程里一個單獨的塊。每個
進程可以含有多個塊,可以共享多個塊中的數據。
程式規定了每個塊中執行緒的執行時間。所有的請求通過
Windows訊息佇列進行
串列化,這樣保證了每個時刻只能訪問一個塊,因而只有一個單獨的
進程可以在某一個時刻得到執行。這種模型比
單執行緒模型的好處在於,可以回響同一時刻的多個用戶請求的
任務而不只是單個用戶請求。但它的性能還不是很好,因為它使用了
串列化的執行緒模型,
任務是一個接一個得到執行的。
·多執行緒塊模型(自由執行緒塊模型)
多執行緒塊模型(MTA)在每個
進程里只有一個塊而不是多個塊。這單個塊控制著多個執行緒而不是單個執行緒。這裡不需要
訊息佇列,因為所有的執行緒都是相同的塊的一個部分,並且可以共享。這樣的
程式比
單執行緒模型和STA的執行速度都要快,因為降低了系統的負載,因而可以最佳化來減少系統idle的時間。這些
應用程式一般比較複雜,因為
程式設計師必須提供
執行緒同步以保證執行緒不會並發的請求相同的資源,因而導致競爭
情況的發生。這裡有必要提供一個鎖機制。但是這樣也許會導致系統死鎖的發生。
執行緒是
進程內部的一個執行單元。系統創建好
進程後,實際上就啟動執行了該進程的主執行執行緒,主執行執行緒以函式
地址形式,比如說main或WinMain函式,將
程式的啟動點提供給Windows系統。主執行執行緒終止了,
進程也就隨之終止。
每一個
進程至少有一個主執行執行緒,它無需由用戶去主動創建,是由系統自動創建的。用戶根據需要在
應用程式中創建其它執行緒,多個執行緒並發地運行於同一個
進程中。一個
進程中的所有執行緒都在該進程的
虛擬地址空間中,共同使用這些虛擬地址空間、
全局變數和系統資源,所以執行緒間的通訊非常方便,
多執行緒技術的套用也較為廣泛。多執行緒可以實現
並行處理,避免了某項
任務長時間占用CPU時間。要說明的一點是,到2015年為止,大多數的計算機都是單處理器(CPU)的,為了運行所有這些執行緒,
作業系統為每個獨立執行緒安排一些CPU時間,作業系統以輪換方式向執行緒提供
時間片,這就給人一種假象,好象這些執行緒都在同時運行。由此可見,如果兩個非常活躍的執行緒為了搶奪對CPU的控制權,線上程切換時會消耗很多的CPU資源,反而會降低系統的性能。這一點在多執行緒編程時應該注意。C++ 11 標準中,STL類庫也實現了多執行緒的類std::thread,使得多執行緒編程更加方便。
NET Framework
在本質上和結構來說,
.NET是一個多執行緒的環境。有兩種主要的多執行緒方法是.NET所提倡的:使用ThreadStart來開始你自己的
進程,直接的(使用ThreadPool.QueueUserWorkItem)或者間接的(比如Stream.BeginRead,或者調用BeginInvoke)使用ThreadPool類。一般來說,你可以"手動"為長時間運行的
任務創建一個新的執行緒,另外對於短時間運行的任務尤其是經常需要開始的那些,
進程池是一個非常好的選擇。
進程池可以同時運行多個
任務,還可以使用框架類。對於資源緊缺需要進行同步的
情況來說,它可以限制某一時刻只允許一個執行緒訪問資源。這種
情況可以視為給執行緒實現了鎖機制。執行緒的基類是System.Threading。所有執行緒通過CLI來進行管理。
·創建執行緒:
Thread DummyThread = new Thread( new ThreadStart(dummyFunction) );
·執行執行緒:
使用Threading命名空間裡的start方法來運行執行緒:
DummyThread.Start ();
·組合執行緒:
經常會出現需要組合多個執行緒的
情況,就是當某個執行緒需要其他執行緒的結束來完成自己的
任務。假設DummyThread必須等待DummyPriorityThread來完成自己的
任務,只需要這樣做:
DummyPriorityThread.Join() ;
·暫停執行緒:
使得執行緒暫停給定的秒
DummyPriorityThread.Sleep(<Time in Second>);
·中止執行緒:
DummyPriorityThread.Abort();
·同步
經常會遇到需要線上程間進行同步的
情況,下面的
代碼給出了一些方法:
usingSystem;usingSystem.Threading;namespaceSynchronizationThreadsExample{classSynchronizationThreadsExample{privateintcounter=0;staticvoidMain(){SynchronizationThreadsExampleSTE=newSynchronizationThreadsExample();STE.ThreadFunction();}publicvoidThreadFunction(){ThreadDummyThread=newThread(newThreadStart(SomeFunction));DummyThread.IsBackground=true;DummyThread.Start();Console.WriteLine("Startedthread");ThreadDummyPriorityThread=newThread(newThreadStart(SomeFunction));DummyPriorityThread.IsBackground=true;//="SecondThread";DummyPriorityThread.Start();Console.WriteLine("Startedthread");DummyThread.Join();DummyPriorityThread.Join();}publicvoidSomeFunction(){try{while(counter<10){inttempCounter=counter;tempCounter++;Thread.Sleep(1);counter=tempCounter;Console.WriteLine("Thread.SomeFunction:"+Thread.+counter);}}catch(ThreadInterruptedExceptionEx){Console.WriteLine("Exceptioninthread"+Thread.);}finally{Console.WriteLine("ThreadExiting."+Thread);}}}}
·使用Interlock
C#提供了一個特殊的類叫做interlocked,就是提供了鎖機制的實現,可以加入如下的
代碼實現鎖機制:
Interlocked.SomeFunction (ref counter);
·使用鎖
這是為了鎖定
代碼關鍵區域以進行同步,鎖定代碼如下:
lock (this){ Some statements ;}
·使用Monitor
當有需要進行執行緒管理的時候可以使用:
Monitor.Enter(this);
其他也有一些方法進行管理,這裡就不一一提及了。
執行緒的缺點
執行緒自然也有缺點,以下列出了一些:
·如果有大量的執行緒,會影響性能,因為
作業系統需要在他們之間切換;
·更多的執行緒需要更多的記憶體空間
·執行緒的中止需要考慮其對程式運行的影響
·通常塊模型數據是在多個執行緒間共享的,需要一個合適的鎖系統替換掉數據共享
Java
Java對多執行緒的支持是非常強大的,他禁止掉了許多的技術細節,讓我們可以輕鬆的開發多執行緒的
應用程式。
Java裡面實現多執行緒,有2個方法
使用 Thread類
class MyThread{ public static void main(String[] args){ new Thread(){ public void run(){ //寫上執行緒需要執行的代碼 } }.start(); }}
使用 Runnable
class MyThread{ public static void main(String[] args){ new Thread(new Runnable() { @Override public void run() { //寫上執行緒需要執行的代碼 } }).start(); } }
這裡推薦使用Thread類來實現多執行緒
C++ 11
ISO C++ 11 標準在STL中提供了std::thread類,因此多執行緒變得非常容易。
#include<thread>usingnamespacestd;voidthreadFunc(){//這裡寫上執行緒的內容}intmain(){threadt(threadFunc);//啟動執行緒t.join();//等待執行緒運行完畢return0;}
優勢
一個採用了
多執行緒技術的
應用程式可以更好地利用
系統資源。其主要優勢在於充分利用了CPU的空閒
時間片,可以用儘可能少的時間來對用戶的要求做出回響,使得
進程的整體運行效率得到較大提高,同時增強了
應用程式的靈活性。更為重要的是,由於同一
進程的所有執行緒是共享同一
記憶體,所以不需要特殊的
數據傳送機制,不需要建立共享存儲區或已分享檔案,從而使得不同
任務之間的協調操作與運行、數據的互動、資源的分配等問題更加易於解決。
執行緒同步
在多執行緒套用中,考慮不同執行緒之間的
數據同步和防止死鎖。當兩個或多個執行緒之間同時等待對方釋放資源的時候就會形成執行緒之間的死鎖。為了防止死鎖的發生,需要通過同步來實現
執行緒安全。在Visual Basic中提供了三種方法來完成執行緒的同步。在Java中可用
synchronized關鍵字。代碼域同步
使用Monitor類可以同步
靜態/實例化的方法的全部
代碼或者部分
代碼段。
手工同步
可以使用不同的同步類(諸如WaitHandle, Mutex, ReaderWriterLock, ManualResetEvent, AutoResetEvent 和Interlocked等)創建自己的同步機制。這種同步方式要求你自己手動的為不同的域和方法同步,這種同步方式也可以用於
進程間的同步和解除由於對共享資源的等待而造成的死鎖。
上下文同步
使用SynchronizationAttribute為ContextBoundObject
對象創建簡單的,自動的同步。這種同步方式僅用於實例化的方法和域的同步。所有在同一個上下文域的
對象共享同一個鎖。
雖然多執行緒能給大家帶來好處,但是也有不少問題需要解決。例如,對於像
磁碟驅動器這樣獨占性
系統資源,由於執行緒可以執行
進程的任何
代碼段,且執行緒的運行是由系統調度自動完成的,具有一定的不確定性,因此就有可能出現兩個執行緒同時對磁碟驅動器進行操作,從而出現操作錯誤;又例如,對於銀行系統的計算機來說,可能使用一個執行緒來更新其用戶
資料庫,而用另外一個執行緒來讀取資料庫以回響儲戶的需要,極有可能讀資料庫的執行緒讀取的是未完全更新的資料庫,因為可能在讀的時候只有一部分數據被更新過。使隸屬於同一
進程的各執行緒協調一致地工作稱為執行緒的同步。下面我們只介紹最常用的四種執行緒同步方式:
事件(event)
HT定義
特點
通過此技術,英特爾成為第一間公司實現在一個實體處理器中,提供兩個邏輯執行緒。之後的
Pentium D縱使不支援超執行緒技術,但就集成了兩個實體核心,所以仍會見到兩個邏輯執行緒。
超執行緒的未來發展,是提升處理器的邏輯執行緒,英特爾有計畫將8核心的處理器,加以配合超執行緒技術,使之成為16個邏輯執行緒的產品。
AMDBulldozer“推土機”
據相關訊息透露,在HotChips會議上,AMD宣布下一代代號為Bulldozer“推土機”的處理器架構將採用單核
多執行緒技術(multi-threadingtechnology),類似於Intel著名的超執行緒技術.
AMD沒有透露有關其多執行緒能力和更多的細節,只說
推土機處理器將在2011年推出,支持單核
多執行緒技術.不過,AMD的做法和Intel的 HT是不同的,更類似於Sun的
同步多執行緒技術(SimultaneousMulti-Threading),由1個物理核心擴展到4個執行緒.“推土機擴展出的單核心多執行緒技術和Intel的
超執行緒採用的是不同方式.”AMD的代表PatConway也證實了這一點. 有趣的是,早些時候AMD還表示暫不考慮SMT或其他多執行緒技術,並將它套用在當下的處理器中.然而,AMD也認同步多執行緒是未來處理器產品大幅提升性能的必要特徵.
推土機是AMD下一代微架構的處理器,事實上,它將是AMD自2003年後第一次對處理器架構進行重大改變.新一代的處理器將提供遠高於現代產品的高性能,同時也加入SSE5
指令集.
首款推土機系列
桌面處理器代號為Orochi,將會擁有超過4個以上的
處理器核心,8M以上的
快取並支持
DDR3記憶體,基於32nm工藝.伺服器版處理器代號為Valencia和Interlagos,這兩款處理器將會擁有6、8以及12個處理器核心.
AMD至今從未採用過同步多執行緒(SMT)也就是Intel所稱的超執行緒技術。雖然這樣的技術在當年的P4時代顯得並無實際用途,但到了2015年為止,越發普及的多執行緒環境讓
超執行緒重新煥發了青春。
發展前景
截止到2014年,以套用環境來看,超執行緒技術可以讓一些特定
應用程式顯著提速達10到15%。除了Intel的在Nehalem、Atom等中引入的
超執行緒,無論IBM的Power系列,Sun的T1/T2/Rock系列等處理器架構都套用了類似的SMT同步
多執行緒技術,用少量的電晶體帶來大幅度的多執行緒性能提升。
一位AMD工程師日前向媒體坦誠,不支持單核
多執行緒技術讓Opteron處理器看起來性能比不上Intel的低端Xeon。據稱,AMD內部高層已經承認,沒有早早引入此類技術是一項技術選擇上的失誤。
不過,AMD副總裁兼
伺服器工作站業務總經理Patrick Patla接受採訪時,並沒有明確透露單核
多執行緒技術的未來,而是繼續重申已經公布的Opteron路線圖:“如果你看一下我們路線圖以及我們在多執行緒處理器市場的表現就會知道,我們相信每條執行緒都擁有完整的核心是目前的最佳選擇。2010年,我們就會推出12核處理器,2011年16核。我們相信未來幾年內我們就能夠完善支持48或64執行緒環境,讓我們來看看2012到2013年會帶來些什麼吧。”
既然2011年才是16核,那么2012到2013直接跳躍到48甚至64核似乎並不是那么正常。另外,Patrick Patla前面句句都在講“核”,而到了後面又變成了“執行緒”,似乎就在暗示到時AMD可能會採納單核
多執行緒技術。