版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
ParallelProgrammingInstructor:ZhangWeizhe(張偉哲)ComputerNetworkandInformationSecurityTechniqueResearchCenter,SchoolofComputerScienceandTechnology,HarbinInstituteofTechnologyProgrammingSharedAddressSpacePlatforms
編程共享地址空間平臺1.進(jìn)程的引入
多個(gè)程序在執(zhí)行時(shí),需要共享系統(tǒng)資源,從而導(dǎo)致各程序在執(zhí)行過程中出現(xiàn)相互制約的關(guān)系,程序的執(zhí)行表現(xiàn)出間斷性的特征。 這些特征都是在程序的執(zhí)行過程中發(fā)生的,是動態(tài)的過程,而傳統(tǒng)的程序本身是一組指令的集合,是一個(gè)靜態(tài)的概念,無法描述程序在內(nèi)存中的執(zhí)行情況,即我們無法從程序的字面上看出它何時(shí)執(zhí)行,何時(shí)停頓,也無法看出它與其它執(zhí)行程序的關(guān)系,因此,程序這個(gè)靜態(tài)概念已不能如實(shí)反映程序并發(fā)執(zhí)行過程的特征。為了深刻描述程序動態(tài)執(zhí)行過程的性質(zhì),人們引入“進(jìn)程(Process)”概念。
進(jìn)程(Process)進(jìn)程(Process)進(jìn)程的概念是60年代初首先由麻省理工學(xué)院的MULTICS系統(tǒng)和IBM公司的CTSS/360系統(tǒng)引入的。進(jìn)程是一個(gè)具有獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動。它可以申請和擁有系統(tǒng)資源,是一個(gè)動態(tài)的概念,是一個(gè)活動的實(shí)體。它不只是程序的代碼,還包括當(dāng)前的活動,通過程序計(jì)數(shù)器的值和處理寄存器的內(nèi)容來表示。進(jìn)程是操作系統(tǒng)中最基本、重要的概念。是多任務(wù)程序系統(tǒng)出現(xiàn)后,為了刻畫系統(tǒng)內(nèi)部出現(xiàn)的動態(tài)情況,描述系統(tǒng)內(nèi)部各道程序的活動規(guī)律引進(jìn)的一個(gè)概念,所有多道程序設(shè)計(jì)操作系統(tǒng)都建立在進(jìn)程的基礎(chǔ)上。進(jìn)程(process)離散的(執(zhí)行)程序任務(wù)集合。一個(gè)進(jìn)程包括:進(jìn)程ID,進(jìn)程組ID,用戶ID,組ID;環(huán)境工作目錄程序指令寄存器堆棧(Stack)堆(Heap)文件描述符信號操作共享庫進(jìn)程間通信工具消息隊(duì)列、管道、信號量、共享內(nèi)存UNIX下進(jìn)程示例進(jìn)程(Process)概念進(jìn)程的特征動態(tài)性:進(jìn)程的實(shí)質(zhì)是程序的一次執(zhí)行過程,進(jìn)程是動態(tài)產(chǎn)生,動態(tài)消亡的。并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行獨(dú)立性:進(jìn)程是一個(gè)能獨(dú)立運(yùn)行的基本單位,同時(shí)也是系統(tǒng)分配資源和調(diào)度的獨(dú)立單位;異步性:由于進(jìn)程間的相互制約,使進(jìn)程具有執(zhí)行的間斷性,即進(jìn)程按各自獨(dú)立的、不可預(yù)知的速度向前推進(jìn)
結(jié)構(gòu)特征:進(jìn)程由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。
進(jìn)程(Process)與程序進(jìn)程為應(yīng)用程序的運(yùn)行實(shí)例,是應(yīng)用程序的一次動態(tài)執(zhí)行。我們可以簡單地理解為:它是操作系統(tǒng)當(dāng)前運(yùn)行的執(zhí)行程序。對應(yīng)用程序來說,進(jìn)程就像一個(gè)大容器。在應(yīng)用程序被運(yùn)行后,就相當(dāng)于將應(yīng)用程序裝進(jìn)容器里了,你可以往容器里加其他東西(如:應(yīng)用程序在運(yùn)行時(shí)所需的變量數(shù)據(jù)、需要引用的DLL文件等),當(dāng)應(yīng)用程序被運(yùn)行兩次時(shí),容器里的東西并不會被倒掉,系統(tǒng)會找一個(gè)新的進(jìn)程容器來容納它。進(jìn)程與程序的關(guān)系程序是指令的有序集合,其本身沒有任何運(yùn)行的含義,是一個(gè)靜態(tài)的概念。而進(jìn)程是程序在處理機(jī)上的一次執(zhí)行過程,它是一個(gè)動態(tài)的概念。
(1)程序可以作為一種軟件資料長期存在,而進(jìn)程是有一定生命期的。程序是永久的,進(jìn)程是暫時(shí)的。
(2)進(jìn)程更能真實(shí)地描述并發(fā),而程序不能;進(jìn)程是由程序和數(shù)據(jù)兩部分組成的。
(3)進(jìn)程具有創(chuàng)建其他進(jìn)程的功能,而程序沒有。
(4)同一程序同時(shí)運(yùn)行于若干個(gè)數(shù)據(jù)集合上,它將屬于若干個(gè)不同的進(jìn)程。也就是說同一程序可以對應(yīng)多個(gè)進(jìn)程。
(5)在傳統(tǒng)的操作系統(tǒng)中,程序并不能獨(dú)立運(yùn)行,作為資源分配和獨(dú)立運(yùn)行的基本單元都是進(jìn)程。WhyThreads?發(fā)揮軟件作用充分利用系統(tǒng)(CPU)資源,提高使用效率多線程的概念線程(thread)是進(jìn)程上下文(context)中執(zhí)行的代碼序列,是進(jìn)程中的一個(gè)實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位,又被稱為輕量級進(jìn)程(lightweightprocess)在支持多線程的系統(tǒng)中,進(jìn)程成為資源分配和保護(hù)的實(shí)體,而線程是被調(diào)度執(zhí)行的基本單元。線程只擁有一點(diǎn)在運(yùn)行中必不可少的資源,但它可與同屬一個(gè)進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源。一個(gè)線程可以創(chuàng)建和撤消另一個(gè)線程,同一進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行。由于線程之間的相互制約,致使線程在運(yùn)行中呈現(xiàn)出間斷性。線程是程序中一個(gè)單一的順序控制流程。在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的工作,稱為多線程。一個(gè)進(jìn)程內(nèi)的線程示例一個(gè)線程對共享的系統(tǒng)資源進(jìn)行修改,在這個(gè)進(jìn)程內(nèi)的其它線程也可以見到這種修改。對于同一個(gè)數(shù)據(jù),可能有兩個(gè)值相同的指針指向這個(gè)數(shù)據(jù)。進(jìn)程內(nèi)的多個(gè)線程可以對同一個(gè)內(nèi)存單元進(jìn)行讀和寫操作,所以必須要采取顯式同步機(jī)制。在同一個(gè)進(jìn)程的地址空間下,線程間的通信消耗更小。對于在一個(gè)進(jìn)程內(nèi)的線程:進(jìn)程與線程的關(guān)系程序在操作系統(tǒng)中作為進(jìn)程方式存在、獲取資源、運(yùn)行。在一個(gè)進(jìn)程內(nèi),線程可以創(chuàng)建其它線程。每個(gè)線程有各自的棧(stack)。一個(gè)進(jìn)程內(nèi)所有的線程共享代碼段和數(shù)據(jù)段。進(jìn)程進(jìn)程與線程的關(guān)系線程和進(jìn)程的區(qū)別在于:子進(jìn)程和父進(jìn)程有不同的代碼和數(shù)據(jù)空間,而多個(gè)線程則共享數(shù)據(jù)空間,每個(gè)線程有自己的執(zhí)行堆棧和程序計(jì)數(shù)器為其執(zhí)行上下文.多線程主要是為了節(jié)約CPU時(shí)間,發(fā)揮利用,根據(jù)具體情況而定.線程的運(yùn)行中需要使用計(jì)算機(jī)的內(nèi)存資源和CPU
多核與線程并行的關(guān)系在單核平臺上的線程并發(fā):在各個(gè)核上可以實(shí)現(xiàn)線程并行:CPU核核1核2多線程的優(yōu)點(diǎn)創(chuàng)建一個(gè)線程比創(chuàng)建一個(gè)進(jìn)程的代價(jià)要小線程的切換比進(jìn)程間的切換代價(jià)小充分利用多處理器數(shù)據(jù)共享數(shù)據(jù)共享使得線程之間的通信比進(jìn)程間的通信更高效快速響應(yīng)特性在系統(tǒng)繁忙的情況下,進(jìn)程通過獨(dú)立的線程及時(shí)響應(yīng)用戶的輸入線程的層次用戶級線程(User-levelthreads)在應(yīng)用軟件中所創(chuàng)建和操縱的線程。內(nèi)核級線程(Kernel-levelthreads)操作系統(tǒng)實(shí)現(xiàn)大多數(shù)線程的方式。硬件線程(Hardwarethreads)
線程在硬件資源上的表現(xiàn)形式。用戶級線程用戶級線程有關(guān)線程的所有管理工作都由在用戶級實(shí)現(xiàn)的線程庫來支持用戶級線程特征用戶級線程的創(chuàng)建和管理等操作無須內(nèi)核參與,操作更快并行性不高,一個(gè)線程被系統(tǒng)阻塞后,整個(gè)進(jìn)程被阻塞內(nèi)核級線程內(nèi)核級線程內(nèi)核級線程的所有管理操作都是由操作系統(tǒng)內(nèi)核完成的特點(diǎn)并行性高,多個(gè)線程可被同時(shí)調(diào)度充分利用多處理器創(chuàng)建和管理代價(jià)高線程計(jì)算模型用戶級線程由可執(zhí)行應(yīng)用程序使用,同時(shí)由用戶級操作系統(tǒng)管理內(nèi)核級線程由操作系統(tǒng)內(nèi)核使用,同時(shí)由內(nèi)核操作系統(tǒng)處理硬件線程由每個(gè)處理器使用執(zhí)行流程執(zhí)行環(huán)境中的線程執(zhí)行流程線程定義和準(zhǔn)備線程運(yùn)行線程執(zhí)行由程序設(shè)計(jì)環(huán)境和編譯器完成由操作系統(tǒng)采用進(jìn)程完成由處理器完成用雙向箭頭表示線程在執(zhí)行之后將結(jié)果返回到用戶空間操作系統(tǒng)內(nèi)部的線程操作系統(tǒng)被分為兩個(gè)截然不同的層次:用戶級(運(yùn)行應(yīng)用程序的層次)內(nèi)核級(系統(tǒng)行為發(fā)生的層次)內(nèi)核級是操作系統(tǒng)的核心,維護(hù)著大量用于追蹤進(jìn)程和線程的表格。內(nèi)核級線程能夠提供更高的性能。并且同一進(jìn)程中的多個(gè)內(nèi)核線程能夠同時(shí)在不同的處理器或者執(zhí)行核上執(zhí)行。如OpenMP,PThread等線程庫用內(nèi)核級線程。硬件上的線程軟件線程的指令都是由硬件來實(shí)際執(zhí)行的。硬件上的多線程技術(shù)需要多個(gè)CPU來增加并行性。(每個(gè)線程都在獨(dú)立的處理器上運(yùn)行)多核CPU提供了兩個(gè)或更多的執(zhí)行核,能夠支持真正的硬件多線程技術(shù)。線程的生命周期線程的標(biāo)識通常用一個(gè)整數(shù)來標(biāo)識一個(gè)線程線程的創(chuàng)建自動創(chuàng)建從main函數(shù)開始的主線程調(diào)用函數(shù)庫接口創(chuàng)建一個(gè)新的線程(pthread_create)線程的終止執(zhí)行完畢,或者調(diào)用了pthread_exit主線程退出導(dǎo)致整個(gè)進(jìn)程會終止線程的狀態(tài)線程的狀態(tài)就緒(ready):線程等待可用的處理器。運(yùn)行(running):線程正在被執(zhí)行。阻塞(blocked):線程正在等待某個(gè)事件的發(fā)生(比如I/O的完成,試圖加鎖一個(gè)被上鎖的互斥量)。終止(terminated):線程從起始函數(shù)中返回或者調(diào)用pthread_exit。線程狀態(tài)的轉(zhuǎn)換線程的同步由于線程共享同一進(jìn)程的內(nèi)存空間,多個(gè)線程可能需要同時(shí)訪問同一個(gè)數(shù)據(jù)。如果沒有正確的保護(hù)措施,對共享數(shù)據(jù)的訪問會造成數(shù)據(jù)的不一致和錯(cuò)誤。常用的同步機(jī)制:臨界區(qū)(criticalsection)信號量(simphore)互斥量(mutex)管程(monitor)互斥量(mutex)在同一時(shí)刻只能有一個(gè)線程能夠?qū)コ饬考渔i線程用互斥量對共享變量counter的互斥訪問:pthread_mutex_tcount_mutex=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock(&count_mutex); counter++;pthread_mutex_unlock(&count_mutex);信號量信號量被定義為一個(gè)整數(shù)變量,用兩個(gè)原子的操作wait和signal來操作信號量wait:當(dāng)執(zhí)行wait時(shí),如果信號量的值大于0,wait操作把信號量的值減1并返回;如果當(dāng)前信號量的值為非正數(shù)則wait會等待。signalsignal操作對信號量的值加1,并喚醒哪些等待的進(jìn)程條件變量如果要等待某個(gè)條件成立(比如x>y),當(dāng)其他線程改變了共享變量的值時(shí),線程應(yīng)當(dāng)重新測試該條件改變共享變量值的線程,給阻塞在條件變量上的線程發(fā)信號,喚醒該線程。典型的條件變量cond來測試x<=y的方法如下(mut為互斥量):1 pthread_mutex_lock(&mut);2 while(x<=y){3 pthread_cond_wait(&cond,&mut);4 }5 pthread_mutex_unlock(&mut);鎖的粒度和死鎖鎖的粒度鎖的粒度是上鎖后保護(hù)的共享數(shù)據(jù)的多少減小鎖的粒度可以提高對共享數(shù)據(jù)訪問的并行性死鎖兩個(gè)線程分別擁有鎖,并等待對方的鎖死鎖避免線程以相同的次序進(jìn)行加鎖非阻塞的加鎖操作并行程序設(shè)計(jì)方法顯式線程(Explicitthreading)微軟Windows線程API,Pthreads,Java線程類等。利用編譯器指導(dǎo)(Compiler-directed)自動并行,OpenMP,IntelThreadingBuildingBlocks等利用并行應(yīng)用庫(Parallellibraries)IntelIPP/MKL,ScaLAPACK,PARDISO,PLAPACK并行程序語言有150種以上消息傳遞(Messagepassing)MPI,OpenMP,PVM,等等。Windows環(huán)境下的多線程編程Windows線程庫介紹Win32API是Windows操作系統(tǒng)為內(nèi)核以及應(yīng)用程序之間提供的接口,將內(nèi)核提供的功能進(jìn)行函數(shù)封裝,應(yīng)用程序通過調(diào)用相關(guān)的函數(shù)獲得相應(yīng)的系統(tǒng)功能。MFC是微軟基礎(chǔ)函數(shù)類庫(MicrosoftFoundationClasses),由微軟提供的,用類庫的方式將Win32API進(jìn)行封裝,以類的方式提供給開發(fā)者。.NET
Framework
由兩部分構(gòu)成:公共語言運(yùn)行庫(Common
Language
Runtime
,CLR)和Framework類庫(Framework
Class
Library
,F(xiàn)CL)。.NET基礎(chǔ)類庫的System.Threading命名空間提供了大量的類和接口來支持多線程。所有與多線程機(jī)制相關(guān)的類都存放在System.Threading命名空間中。創(chuàng)建線程管理線程使用Windows事件進(jìn)行線程通信線程同步原子操作線程池線程優(yōu)先級處理器親和帶有線程支持的用戶級線程機(jī)制Windows多線程應(yīng)用程序的編譯和鏈接微軟Win32/MFC線程API使用win32線程APIWin32函數(shù)庫中提供了操作多線程的函數(shù),包括創(chuàng)建線程、管理線程、終止線程、線程同步等接口。線程函數(shù)DWORDWINAPIThreadFunc(LPVOIDlpvThreadParm);線程創(chuàng)建HANDLECreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINElpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);也可以用_beginthread(多線程函數(shù)名,0,NULL)//須引入”process.h”使用win32線程API—HANDLE句柄是一種指向指針的指針。我們知道,所謂指針是一種內(nèi)存地址。應(yīng)用程序啟動后,組成這個(gè)程序的各對象是住留在內(nèi)存的。如果簡單地理解,似乎我們只要獲知這個(gè)內(nèi)存的首地址,那么就可以隨時(shí)用這個(gè)地址訪問對象。但是,如果您真的這樣認(rèn)為,那么您就大錯(cuò)特錯(cuò)了。Windows是一個(gè)以虛擬內(nèi)存為基礎(chǔ)的操作系統(tǒng)。在這種系統(tǒng)環(huán)境下,Windows內(nèi)存管理器經(jīng)常在內(nèi)存中來回移動對象,依此來滿足各種應(yīng)用程序的內(nèi)存需要。對象被移動意味著它的地址變化了。如果地址總是如此變化,我們該到哪里去找該對象呢?為了解決這個(gè)問題,Windows操作系統(tǒng)為各應(yīng)用程序騰出一些內(nèi)存儲地址,用來專門登記各應(yīng)用對象在內(nèi)存中的地址變化,而這個(gè)地址(存儲單元的位置)本身是不變的。Windows中的句柄實(shí)際上是一個(gè)唯一的數(shù)字,它引用一個(gè)Windows對象,例如窗口或者圖標(biāo)等。。使用win32線程API—HANDLEWindows內(nèi)存管理器在移動對象在內(nèi)存中的位置后,把對象新的地址告知這個(gè)句柄地址來保存。這樣我們只需記住這個(gè)句柄地址就可以間接地知道對象具體在內(nèi)存中的哪個(gè)位置。這個(gè)地址是在對象裝載(Load)時(shí)由系統(tǒng)分配給的,當(dāng)系統(tǒng)卸載時(shí)(Unload)又釋放給系統(tǒng)。句柄地址(穩(wěn)定)→記載著對象在內(nèi)存中的地址→對象在內(nèi)存中的地址(不穩(wěn)定)→實(shí)際對象但是,必須注意的是程序每次重新啟動,系統(tǒng)不能保證分配給這個(gè)程序的句柄還是原來的那個(gè)句柄,而且絕大多數(shù)情況的確不一樣的。假如我們把進(jìn)入電影院看電影看成是一個(gè)應(yīng)用程序的啟動運(yùn)行,那么系統(tǒng)給應(yīng)用程序分配的句柄總是不一樣,這和每次電影院售給我們的門票總是不同的一個(gè)座位是一樣的道理。使用WIN32線程API—
線程函數(shù)MyThreadStart(LPVOIDp)即為線程的執(zhí)行函數(shù)線程函數(shù)—CreateThreadlpThreadAttribute Thisisoptionalsecurityforchildprocesses.ItcanbeNULL.這是子進(jìn)程的可選安全性。它可以為NULL。dwStackSize Thisisstacksizeinbytes.Itcanbe0,whichmeansusedefault(usually1megabyte).這是堆棧大?。ㄒ宰止?jié)為單位)。它可以是0,這意味著使用默認(rèn)(通常是1兆字節(jié))。lpStartAddress ThisisagloballyvisiblefunctiondeclaredDWORDWINAPI.Thisisthefunctionforthethreadtobeginexecution.這是一個(gè)全局可見的函數(shù),聲明為DWORDWINAPI。這是線程開始執(zhí)行的函數(shù)。lpParameter Thisisapointertotheoneparameterfor"lpStartAddress"function.Useapointertoastructuretopassmultipleparameters.這是一個(gè)指向“l(fā)pStartAddress”函數(shù)的一個(gè)參數(shù)的指針。使用指向結(jié)構(gòu)的指針傳遞多個(gè)參數(shù)。dwCreationFlags Thiscreatesathreadandstartsorsuspendsit.Use0tostart;otherwiseuseCREATE_SUSPENDED.這將創(chuàng)建一個(gè)線程并啟動或暫停它。使用0開始;否則使用CREATE_SUSPENDED。lpThreadId Thisisanoutputparameterandreturnsaunique(acrossthesystem)integerforthethread.ItcanbeNULL.這是一個(gè)輸出參數(shù),并為線程返回一個(gè)唯一(跨系統(tǒng))整數(shù)。它可以為NULL。線程管理設(shè)置線程的優(yōu)先級線程優(yōu)先級=進(jìn)程優(yōu)先級+線程相對優(yōu)先級BoolSetThreadPriority(HANDLEhPriority,intnPriority)線程的掛起與恢復(fù)進(jìn)程中的每個(gè)線程都有掛起計(jì)數(shù)器(suspendcount)。當(dāng)掛起計(jì)數(shù)器值為0時(shí),線程被執(zhí)行;當(dāng)掛起計(jì)數(shù)器值大于0時(shí),調(diào)度器不去調(diào)度該線程。DWORDSuspendThread(HANDLEhThread);DWORDResumeThread(HANDLEhThread);線程等待一組能使線程阻塞其自身執(zhí)行的等待函數(shù)WaitForSingleObject、WaitForMultipleObject。線程終結(jié)VOIDExitThread(DWORDdwExitCode);線程的退出釋放操作系統(tǒng)資源在程序結(jié)束前要清除線程及其所占資源線程退出調(diào)用函數(shù):
BOOLCloseHandle(HANDLEhObject);42Example:ThreadCreation#include<stdio.h>#include<windows.h>DWORDWINAPIhelloFunc(LPVOIDarg){printf(“HelloThread\n”);return0;}main(){ HANDLEhThread=CreateThread(NULL,0,helloFunc,NULL,0,NULL);}Whathappens?Whenprocessgoes,allthreadgo;43Example:ThreadCreation#include<stdio.h>#include<windows.h>BOOLthreadDone=FALSE;DWORDWINAPIhelloFunc(LPVOIDarg){printf(“HelloThread\n”);threadDone=TRUE;return0;}main(){ HANDLEhThread=CreateThread(NULL,0,helloFunc,NULL,0,NULL);while(!threadDone);}Agoodsolution?WaitingforaThreadWaitforoneobject(thread)Callingthreadwaits(blocks)until調(diào)用線程等待(塊)直到?Timeexpires時(shí)間到期 ?Returncodeusedtoindicatethis返回代碼用于指示?Threadexits(handleissignaled)線程退出 ?UseINFINITEtowaituntilthreadtermination使用INFINITE等待線程終止DoesnotuseCPUcycles不使用CPU周期45Example:ThreadCreation#include<stdio.h>#include<windows.h>DWORDWINAPIhelloFunc(LPVOIDarg){printf(“HelloThread\n”);return0;}main(){ HANDLEhThread=CreateThread(NULL,0,helloFunc, NULL,0,NULL);WaitForSingleObjects(hThread,INFINITE);}WaitingforManyThreadWaitforupto64objects(threads)Waitforall:fWaitAll==TRUEWaitforany:fWaitAll==FALSE?ReturnvalueisfirstarrayindexfoundNotesonWaitFor*FunctionsHandleasparameterUsedfordifferenttypesofobjects用于不同類型的對象Kernelobjectshavetwostates內(nèi)核對象有兩個(gè)狀態(tài) ?Signaled信號 ?Non-signaled無信號Behaviorisdefinedbyobjectreferredtobyhandle行為由句柄引用的對象定義 ?Thread:signaledmeansterminated線程:用信號表示終止Example:MultipleThreadsModifythepreviousexamplecodetoprintout?Appropriate“HelloThread”message?Uniquethreadnumber?Usefor-loopvariableofCreateThreadloopSampleoutput:Example2:HelloThreadsExample2:HelloThreadsWhat’swrong?WhatisprintedformyNum?HelloThreadsTimeline數(shù)據(jù)競爭(RaceConditions)Concurrentaccessofsamevariablebymultiplethreads多個(gè)線程同時(shí)訪問同一個(gè)變量?Read/Writeconflict讀/寫沖突?Write/Writeconflict寫/寫沖突Mostcommonerrorinconcurrentprograms并發(fā)程序中最常見的錯(cuò)誤Maynotbeapparentatalltimes也許不是在任何時(shí)候都明顯HowtoAvoidDataRacesScopevariablestobelocaltothreads范圍變量為線程本地的?Variablesdeclaredwithinthreadedfunctions在線程函數(shù)中聲明的變量?Allocateonthread’sstack在線程堆棧上分配?TLS(ThreadLocalStorage)線程本地存儲Controlsharedaccesswithcriticalregions控制與關(guān)鍵區(qū)域的共享訪問?Mutualexclusionandsynchronization互斥和同步?Lock,semaphore,event,criticalsection,mutex…鎖定,信號量,事件,關(guān)鍵部分,互斥程序修改方案Solution–
“Local”StorageCanwork,butnotwiseidea!線程執(zhí)行和資源存取線程之間通信的兩個(gè)基本問題是互斥和同步線程同步是指線程之間所具有的一種制約關(guān)系,一個(gè)線程的執(zhí)行依賴另一個(gè)線程的消息,當(dāng)它沒有得到另一個(gè)線程的消息時(shí)應(yīng)該等待,直到消息到達(dá)時(shí)才被喚醒。線程互斥是指對于共享資源,在各線程訪問時(shí)的排它性。Win32線程同步的實(shí)現(xiàn)全局變量事件(Event)臨界區(qū)(Criticalsection)互斥量(Mutex)信號量(Semaphore)Win32線程同步的實(shí)現(xiàn)(續(xù))臨界區(qū)一種防止多個(gè)線程同時(shí)執(zhí)行一個(gè)特定代碼段的機(jī)制適用于多個(gè)線程操作之間沒有先后順序但要求互斥的同步。多個(gè)線程訪問同一個(gè)臨界區(qū)的原則:一次最多只能一個(gè)線程停留在臨界區(qū)內(nèi)
不能讓一個(gè)線程無限地停留在臨界區(qū)內(nèi),否則其他線程將不能進(jìn)入該臨界區(qū)互斥量通常用于協(xié)調(diào)多個(gè)線程或進(jìn)程的活動,通過“鎖定”和“取消鎖定”資源,控制對共享資源的訪問。信號量信號量是一個(gè)核心對象,擁有一個(gè)計(jì)數(shù)器,可用來管理大量有限的系統(tǒng)資源。當(dāng)計(jì)數(shù)值大于零時(shí),信號量為有信號狀態(tài);當(dāng)計(jì)數(shù)值為零時(shí),信號量處于無信號狀態(tài)。Win32線程同步的實(shí)現(xiàn)—全局變量使用全局變量保存線程中的關(guān)鍵數(shù)據(jù)或信息。Win32線程同步的實(shí)現(xiàn)—事件(Event)Usedtosignalotherthreadsthatsomeeventhasoccurred用于向其他線程發(fā)出一些事件發(fā)生的信號 ?Dataisavailable,messageisready數(shù)據(jù)可用,消息就緒ThreadswaitforsignalwithWaitFor*function線程使用WaitFor*函數(shù)等待信號Twokindsofevents兩種事件 ?Auto-reset自動復(fù)位 ?Manual-reset手動復(fù)位Caution:BecarefulwhenusingWaitForMultipleObjectstowaitforALLeventsWin32線程同步的實(shí)現(xiàn)—事件(Event)SetbManualResettoTRUEformanual-resetevent;FALSEforauto-resetevent手動復(fù)位為TRUE,自動復(fù)位為FALSESetbInitialStatetoTRUEforeventtobegininsignaledstate;FALSEtobeginunsignaledWin32線程同步的實(shí)現(xiàn)—事件(Event)Win32線程同步的實(shí)現(xiàn)—事件Win32線程同步的實(shí)現(xiàn)—CriticalSectionNewtype
?CRITICAL_SECTIONcs;Createanddestroyoperations
?InitializeCriticalSection(&cs)
?DeleteCriticalSection(&cs);Win32線程同步的實(shí)現(xiàn)—CriticalSectionWin32線程同步的實(shí)現(xiàn)—Mutexes Mutex對象的狀態(tài)在它不被任何線程擁有時(shí)才有信號,而當(dāng)它被擁有時(shí)則無信號。Mutex對象很適合用來協(xié)調(diào)多個(gè)線程對共享資源的互斥訪問。 可按下列步驟使用該對象: 首先,建立互斥體對象,得到句柄:
HANDLECreateMutex(); 然后,在線程可能產(chǎn)生沖突的區(qū)域前(即訪問共享資源之前)調(diào)用 WaitForSingleObject,將句柄傳給函數(shù),請求占用互斥對象:
dwWaitResult=WaitForSingleObject(hMutex,5000L); 共享資源訪問結(jié)束,釋放對互斥體對象的占用:
ReleaseMutex(hMutex); 互斥體對象在同一時(shí)刻只能被一個(gè)線程占用,當(dāng)互斥體對象被一個(gè)線程占用時(shí),若有另一線程想占用它,則必須等到前一線程釋放后才能成功。Win32線程同步的實(shí)現(xiàn)—MutexesWin32線程同步的實(shí)現(xiàn)—Mutexes(續(xù))Win32線程同步的實(shí)現(xiàn)—Semaphore
信號對象允許同時(shí)對多個(gè)線程共享資源進(jìn)行訪問,在創(chuàng)建對象時(shí)指定最大可同時(shí)訪問的線程數(shù)。當(dāng)一個(gè)線程申請?jiān)L問成功后,信號對象中的計(jì)數(shù)器減一,調(diào)用ReleaseSemaphore函數(shù)后,信號對象中的計(jì)數(shù)器加一。其中,計(jì)數(shù)器值大于或等于0,但小于或等于創(chuàng)建時(shí)指定的最大值。如果一個(gè)應(yīng)用在創(chuàng)建一個(gè)信號對象時(shí),將其計(jì)數(shù)器的初始值設(shè)為0,就阻塞了其他線程,保護(hù)了資源。等初始化完成后,調(diào)用ReleaseSemaphore函數(shù)將其計(jì)數(shù)器增加至最大值,則可進(jìn)行正常的存取訪問??砂聪铝胁襟E使用該對象:首先,創(chuàng)建信號對象:
HANDLECreateSemaphore();或者打開一個(gè)信號對象:HANDLEOpenSemaphore();然后,在線程訪問共享資源之前調(diào)用:WaitForSingleObject;共享資源訪問完成后,應(yīng)釋放對信號對象的占用: ReleaseSemaphore();Win32線程同步的實(shí)現(xiàn)—SemaphoreValueoflSemMaxmustbe1orgreaterValueoflSemInitialmustbe?greaterthanorequaltozero,?lessthanorequaltolSemMax,and?cannotgooutsideofrangeWin32線程同步的實(shí)現(xiàn)—Semaphore(續(xù))UseWaitForSingleObjecttowaitonsemaphore?Ifcountis==0,threadwaits?Decrementcountby1whencount>0Incrementsemaphore(Postoperation)?IncreasesemaphorecountbycReleaseCount?ReturnsthepreviouscountthroughlpPreviousCountWin32線程同步的實(shí)現(xiàn)—Semaphore(舉例)Mainthreadopensinputfile,waitsforthreadterminationThreadswillReadlinefrominputfileCountallfive-letterwordsinlineWin32線程同步的實(shí)現(xiàn)—Semaphore(舉例續(xù))Mainthreadopensinputfile,waitsforthreadterminationThreadswillReadlinefrominputfileCountallfive-letterwordsinlineMFC線程同步的實(shí)現(xiàn)AfxBeginThread()來創(chuàng)建一個(gè)CWinThread對象。CWinThread::CreateThread()函數(shù)用來啟動新的線程MFC同步類CCriticalSection只允許當(dāng)前進(jìn)程中的一個(gè)線程訪問某個(gè)對象的同步類CMutes只允許系統(tǒng)中一個(gè)進(jìn)程內(nèi)的一個(gè)線程訪問某個(gè)對象的同步類CSymaphore只允許一到某個(gè)指定數(shù)目個(gè)線程同時(shí)訪問某個(gè)對象的同步類CEvent當(dāng)某個(gè)事件發(fā)生時(shí)通知一個(gè)應(yīng)用程序的同步類微軟.NET框架的線程API通用語言運(yùn)行時(shí)(CommonLanguageRuntime:CLR)微軟2002年引入的一種新的執(zhí)行環(huán)境。C#.NET框架、CLR以及程序執(zhí)行所需要的工具合起來,稱為“.NET”。內(nèi)容創(chuàng)建管理線程池同步①創(chuàng)建線程usingSystem;usingSystem.Threading;······Threadt=newThread(newThreadStart(ThreadProc));更為精練創(chuàng)建舉例usingSystem;usingSystem.Threading;publicclassThreadExample{ publicstaticvoidThreadProc(){ for(inti=0;i<10;i++){ Console.WriteLine("ThreadProc:{0}",i); Thread.Sleep(0);}} publicstaticvoidMain(){ Console.WriteLine("Mainthread:Startasecondthread."); Threadt=newThread(newThreadStart(ThreadProc)); t.Start();
for(inti=0;i<4;i++){ Console.WriteLine("Mainthread:Dosomework."); Thread.Sleep(0);} Console.WriteLine("Mainthread:CallJoin(),towaituntilThreadProcends."); t.Join(); Console.WriteLine("Mainthread:ThreadProc.Joinhasreturned.PressEntertoendprogram."); Console.ReadLine();}}線程優(yōu)先級優(yōu)先級設(shè)置方法ThreadthreadOne=newThread(startDelegate);threadOne.Name="ThreadOne";ThreadthreadTwo=newThread(startDelegate);threadTwo.Name="ThreadTwo";threadTwo.Priority=ThreadPriority.BelowNormal;
threadOne.Start();threadTwo.Start();線程優(yōu)先級優(yōu)先級級別級別說明最高(Highest)可以將Thread安排在具有任何其他優(yōu)先級的線程之前。
普通上(AboveNormal)可以將Thread安排在具有Highest優(yōu)先級的線程之后,在具有Normal優(yōu)先級的線程之前。
普通(Normal)可以將Thread安排在具有AboveNormal優(yōu)先級的線程之后,在具有BelowNormal優(yōu)先級的線程之前。默認(rèn)情況下,線程具有Normal優(yōu)先級。
普通下(BelowNormal)可以將Thread安排在具有Normal優(yōu)先級的線程之后,在具有Lowest優(yōu)先級的線程之前。
最低(Lowest)可以將Thread安排在具有任何其他優(yōu)先級的線程之后。
②管理線程終止線程等待線程掛起合恢復(fù)線程Thre
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 四川省涼山彝族自治州(2024年-2025年小學(xué)六年級語文)部編版競賽題(下學(xué)期)試卷及答案
- 2021醫(yī)藥護(hù)士工作年終總結(jié)范文
- 贊美教師演講稿(15篇)
- 軍訓(xùn)活動學(xué)生總結(jié)10篇
- 共青團(tuán)建團(tuán)100周年心得感言(5篇)
- 2024年年托育項(xiàng)目申請報(bào)告
- 2024年強(qiáng)振加速度儀項(xiàng)目規(guī)劃申請報(bào)告模板
- 輔導(dǎo)工作計(jì)劃4篇
- 鋼屋面工程施工吊裝方案
- 2024年左旋肉堿項(xiàng)目提案報(bào)告
- JTS-196-1-2009海港集裝箱碼頭建設(shè)標(biāo)準(zhǔn)
- 《經(jīng)濟(jì)學(xué)原理》題庫(含參考答案)
- 互聯(lián)網(wǎng)+大學(xué)生創(chuàng)新創(chuàng)業(yè)大賽“智慧老人”健康系統(tǒng)計(jì)劃書
- 偉大的《紅樓夢》智慧樹知到期末考試答案章節(jié)答案2024年北京大學(xué)
- 2024年中儲糧集團(tuán)招聘筆試參考題庫附帶答案詳解
- 24春國家開放大學(xué)《地域文化(本)》形考任務(wù)1-4參考答案
- 高等數(shù)學(xué)(高職教育)全套教學(xué)課件
- 瑞幸咖啡品牌營銷策略研究報(bào)告
- 醫(yī)學(xué)科研的道德與倫理
- 小學(xué)一年級上冊數(shù)學(xué)口算訓(xùn)練題
- 江西省景德鎮(zhèn)市2023-2024學(xué)年高二上學(xué)期1月期末考試物理試題
評論
0/150
提交評論