多執行緒(多執行緒)

多執行緒

多執行緒一般指本詞條

多執行緒(英語:multithreading),是指從軟體或者硬體上實現多個執行緒並發執行的技術。具有多執行緒能力的計算機因有硬體支持而能夠在同一時間執行多於一個執行緒,進而提升整體處理性能。具有這種能力的系統包括對稱多處理機、多核心處理器以及晶片級多處理(Chip-level multithreading)或同時多執行緒(Simultaneous multithreading)處理器。在一個程式中,這些獨立運行的程式片段叫作“執行緒”(Thread),利用它編程的概念就叫作“多執行緒處理(Multithreading)”。具有多執行緒能力的計算機因有硬體支持而能夠在同一時間執行多於一個執行緒(台灣譯作“執行緒”),進而提升整體處理性能。

基本介紹

  • 中文名:多執行緒
  • 外文名:multithreading
  • 用途:實現多個執行緒並發執行的技術
  • 對象:計算機
定義,用途,硬體支持,執行緒,優點,缺點,NET Framework,Java,C++ 11,優勢,執行緒同步,代碼域同步,上下文同步,HT定義,特點,AMDBulldozer“推土機”,發展前景,

定義

在計算機編程中,一個基本的概念就是同時對多個任務加以控制。許多程式設計問題都要求程式能夠停下手
頭的工作,改為處理其他一些問題,再返回主進程。可以通過多種途徑達到這個目的。最開始的時候,那些掌握機器低級語言的程式設計師編寫一些“中斷服務例程”,主進程的暫停是通過硬體級的中斷實現的。儘管這是一種有用的方法,但編出的程式很難移植,由此造成了另一類的代價高昂問題。中斷對那些實時性很強的任務來說是很有必要的。但對於其他許多問題,只要求將問題劃分進入獨立運行的程式片斷中,使整個程式能更迅速地回響用戶的請求。
多執行緒多執行緒
最開始,執行緒只是用於分配單個處理器的處理時間的一種工具。但假如作業系統本身支持多個處理器,那么每個執行緒都可分配給一個不同的處理器,真正進入“並行運算”狀態。從程式設計語言的角度看,多執行緒操作最有價值的特性之一就是程式設計師不必關心到底使用了多少個處理器。程式在邏輯意義上被分割為數個執行緒;假如機器本身安裝了多個處理器,那么程式會運行得更快,毋需作出任何特殊的調校。根據前面的論述,大家可能感覺執行緒處理非常簡單。但必須注意一個問題:共享資源!如果有多個執行緒同時運行,而且它們試圖訪問相同的資源,就會遇到一個問題。舉個例子來說,兩個執行緒不能將信息同時傳送給一台印表機。為解決這個問題,對那些可共享的資源來說(比如印表機),它們在使用期間必須進入鎖定狀態。所以一個執行緒可將資源鎖定,在完成了它的任務後,再解開(釋放)這個鎖,使其他執行緒可以接著使用同樣的資源。
多執行緒是為了同步完成多項任務,不是為了提高運行效率,而是為了提高資源使用效率來提高系統的效率。執行緒是在同一時間需要完成多項任務的時候實現的。
最簡單的比喻多執行緒就像火車的每一節車廂,而進程則是火車。車廂離開火車是無法跑動的,同理火車也不可能只有一節車廂。多執行緒的出現就是為了提高效率。同時它的出現也帶來了一些問題。

用途

在大多數研究領域內是要求執行緒調度程式要能夠快速選擇其中一個已就緒執行緒去運行,而不是一個一個運行而降低效率。所以要讓調度程式去分辨執行緒的優先權是很重要的。而執行緒調度程式可能是以硬體、軟體,或是軟硬體並存的形式存在。
而另一個研究領域則是要研究何種事件(高速快取失敗、內部運行連續性、使用DMA等)會造成執行緒切換。
如果多執行緒的方案會複製所有軟體可見的狀態,包括特許的控制登錄、TLB 等,那就能夠讓虛擬機去創造各式執行緒。這樣子就允許在相同的處理器中每個執行緒跑各自的作業系統。換句話說,如果只有存儲了用戶模式的狀態,就能夠讓相同的裸晶大小的晶片在一段時間內處理更多的執行緒。

硬體支持

多執行緒硬體支持的目標,即支持快速進行就緒態執行緒、執行態執行緒間的切換。為達成這個目標,需要硬體實現保存、恢復程式看得見的暫存器以及一些對程式執行有影響的控制暫存器(如程式計數器PC、程式狀態暫存器SR)。從一個執行緒切換到另一個執行緒對硬體來講意味著保存當前執行緒的一組暫存器的值,並恢復即將執行執行緒的一組暫存器的值。
新增這些功能的硬體有以下優勢:
  • 執行緒切換能夠在一個 CPU 周期內完成(有些硬體甚至沒有開銷,上個周期在運行執行緒A,下個周期就已在運行執行緒B)。
  • 每個執行緒看起來就像是獨自運行的,即沒有與其他執行緒共享硬體資源。對作業系統來說,通常每個執行緒都被視做獨占一個處理器,這樣將簡化系統軟體的設計(尤其是對於支持多執行緒的作業系統)。
為了在各個執行緒間有效率的進行切換,每個執行緒需要保存自己的一組暫存器集(register set)。有些硬體設計成每個處理器核心具有兩組暫存器檔案,以實現在多個執行緒間快速切換。

執行緒

定義
英文:Thread
每個正在系統上運行的程式都是一個進程。每個進程包含一到多個執行緒。進程也可能是整個程式或者是部分程式的動態執行。執行緒是一組指令的集合,或者是程式的特殊段,它可以在程式里獨立執行。也可以把它理解為代碼運行的上下文。所以執行緒基本上是輕量級的進程,它負責在單個程式里執行多任務。通常由作業系統負責多個執行緒的調度和執行。
執行緒是程式中一個單一的順序控制流程.在單個程式中同時運行多個執行緒完成不同的工作,稱為多執行緒.
執行緒和進程的區別在於,子進程和父進程有不同的代碼和數據空間,而多個執行緒則共享數據空間,每個執行緒有自己的執行堆疊程式計數器為其執行上下文.多執行緒主要是為了節約CPU時間,發揮利用,根據具體情況而定. 執行緒的運行中需要使用計算機的記憶體資源和CPU。

優點

·使用執行緒可以把占據時間長的程式中的任務放到後台去處理
·用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度
·程式的運行速度可能加快
·在一些等待的任務實現上如用戶輸入、檔案讀寫和網路收發數據等,執行緒就比較有用了。在這種情況下可以釋放一些珍貴的資源如記憶體占用等等。
.多執行緒技術在IOS軟體開發中也有舉足輕重的位置。
.執行緒套用的好處還有很多,就不一一說明了

缺點

·如果有大量的執行緒,會影響性能,因為作業系統需要在它們之間切換。
·更多的執行緒需要更多的記憶體空間。
·執行緒可能會給程式帶來更多“bug”,因此要小心使用。
·執行緒的中止需要考慮其對程式運行的影響。
·通常塊模型數據是在多個執行緒間共享的,需要防止執行緒死鎖情況的發生。
一些執行緒模型的背景
可以重點討論一下在Win32環境中常用的一些模型。
·單執行緒模型
在這種執行緒模型中,一個進程中只能有一個執行緒,剩下的進程必須等待當前的執行緒執行完。這種模型的缺點在於系統完成一個很小的任務都必須占用很長的時間。
·塊執行緒模型(單執行緒多塊模型STA)
這種模型里,一個程式里可能會包含多個執行的執行緒。在這裡,每個執行緒被分為進程里一個單獨的塊。每個進程可以含有多個塊,可以共享多個塊中的數據。程式規定了每個塊中執行緒的執行時間。所有的請求通過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對象的實例。Thread的構造函式接受一個參數
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);
其他也有一些方法進行管理,這裡就不一一提及了。
執行緒的缺點
執行緒自然也有缺點,以下列出了一些:
·如果有大量的執行緒,會影響性能,因為作業系統需要在他們之間切換;
·更多的執行緒需要更多的記憶體空間
·執行緒會給程式帶來更多的bug,因此要小心使用
·執行緒的中止需要考慮其對程式運行的影響
·通常塊模型數據是在多個執行緒間共享的,需要一個合適的鎖系統替換掉數據共享

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對象創建簡單的,自動的同步。這種同步方式僅用於實例化的方法和域的同步。所有在同一個上下文域的對象共享同一個鎖。
雖然多執行緒能給大家帶來好處,但是也有不少問題需要解決。例如,對於像磁碟驅動器這樣獨占性系統資源,由於執行緒可以執行進程的任何代碼段,且執行緒的運行是由系統調度自動完成的,具有一定的不確定性,因此就有可能出現兩個執行緒同時對磁碟驅動器進行操作,從而出現操作錯誤;又例如,對於銀行系統的計算機來說,可能使用一個執行緒來更新其用戶資料庫,而用另外一個執行緒來讀取資料庫以回響儲戶的需要,極有可能讀資料庫的執行緒讀取的是未完全更新的資料庫,因為可能在讀的時候只有一部分數據被更新過。使隸屬於同一進程的各執行緒協調一致地工作稱為執行緒的同步。下面我們只介紹最常用的四種執行緒同步方式:
臨界區(critical section)
事件(event)
互斥量(mutex)
信號量(semaphore)
通過這些類,可以比較容易地做到執行緒同步

HT定義

超執行緒(HT)是英特爾所研發的一種技術,於2002年發布。超執行緒的英文是HT技術,全名為Hyper-Threading,中文又名超執行緒超執行緒技術原先只套用於Xeon處理器中,當時稱為Super-Threading。之後陸續套用在Pentium 4中,將技術主流化。早期代號為Jackson。

特點

通過此技術,英特爾成為第一間公司實現在一個實體處理器中,提供兩個邏輯執行緒。之後的Pentium D縱使不支援超執行緒技術,但就集成了兩個實體核心,所以仍會見到兩個邏輯執行緒。超執行緒的未來發展,是提升處理器的邏輯執行緒,英特爾有計畫將8核心的處理器,加以配合超執行緒技術,使之成為16個邏輯執行緒的產品。
英特爾表示,超執行緒技術讓(P4)處理器增加5%的裸晶面積,就可以換來15%~30%的效能提升。但實際上,在某些程式或未對多執行緒編譯的程式而言,超執行緒反而會降低效能。除此之外,超執行緒技術亦要作業系統的配合,普通支援多處理器技術的系統亦未必能充分發揮該技術。例如Windows 2000,英特爾並不鼓勵使用者在此系統中利用超執行緒。原先不支援多核心Windows XPHome Edition卻支援超執行緒技術。

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可能會採納單核多執行緒技術

相關詞條

熱門詞條

聯絡我們