

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p><b> 摘要</b></p><p> 隨著嵌入式Linux系統(tǒng)的廣泛應(yīng)用和發(fā)展,多線程技術(shù)日益完善。使用多線程編程可以大大增進(jìn)效率。將任務(wù)相關(guān)聯(lián)的各個(gè)線程運(yùn)行在統(tǒng)一地址空間上,并且共享全局變量和內(nèi)存,這樣線程之間共享數(shù)據(jù)很方便,相互間通信也容易,十分利于多線程間的數(shù)據(jù)交互。同時(shí),由于ARM與Linux系統(tǒng)的出色表現(xiàn),基于ARM的Linux嵌入式系統(tǒng)的多線程數(shù)據(jù)交互在
2、實(shí)際應(yīng)用得到很好的推廣,多線程數(shù)據(jù)交互的性能也越來越受到重視[1][2][10]。研究如何測(cè)試分析多線程間數(shù)據(jù)交互問題以及數(shù)據(jù)交互的方式方法十分有意義。這能為多線程的編程提供很好的參考。</p><p> 本文著重研究多線程下數(shù)據(jù)交互的方式方法,并且測(cè)試各種數(shù)據(jù)交互方式的系統(tǒng)性能以及優(yōu)缺點(diǎn)。主要探討了基于互斥鎖的多線程數(shù)據(jù)交互方式、基于條件變量的多線程數(shù)據(jù)交互方式以及基于讀寫鎖的多線程數(shù)據(jù)交互方式。通過設(shè)計(jì)綜合
3、程序,創(chuàng)建六個(gè)線程,分別實(shí)現(xiàn)消費(fèi)者、生產(chǎn)者、讀取、寫入數(shù)據(jù)等功能,相互間采用不同的方式方法進(jìn)行數(shù)據(jù)交互,以此來研究多線程數(shù)據(jù)交互的編程,測(cè)試多線程數(shù)據(jù)交互的性能。整個(gè)設(shè)計(jì)采用C語言,并且調(diào)用線程標(biāo)準(zhǔn)庫(kù)pthread。以此完成整個(gè)設(shè)計(jì)研究。</p><p> 關(guān)鍵詞: Linux; 多線程;ARM;數(shù)據(jù)交互; </p><p><b> Abstract</b>&l
4、t;/p><p> With the extensive application and development of embedded Linux systems, multi-threading technology has improved steadily. Using multi-threaded programming can greatly improve efficiency. If the thr
5、eads in the associated tasks running in the unified address space and shared global variables and memory, the data communication with each other will easily, and it will very conducive to the data exchange between multip
6、le threads. At the same time, as the excellent performance of the ARM and Linux s</p><p> This paper focuses on the ways and means of data exchange in multi-threaded, and test the system performance, as wel
7、l as research the advantages and disadvantages of various data interactively. It will aim at the data interactively based on multi-threaded mutex, condition variable multi-threaded data interactively, and read and write
8、multi-threaded lock . The design process will create six threads, respectively, to achieve the consumer, producer, read, write data and functions among different wa</p><p> Keywords: Linux; multi-threaded;
9、ARM; data exchange;</p><p><b> 1緒論</b></p><p> 隨著嵌入式系統(tǒng)的發(fā)展,多線程編程技術(shù)的應(yīng)用越來越廣泛。特別是在嵌入式系統(tǒng)中存在大量的數(shù)據(jù)交互,采用多線程技術(shù)就具有得天獨(dú)厚的數(shù)據(jù)交互優(yōu)勢(shì)[3]。因此,總結(jié)多線程中數(shù)據(jù)交互的方式,分析數(shù)據(jù)交互的性能具有重要的意義。</p><p> 1.1研
10、究背景和意義</p><p> 在嵌入式系統(tǒng)高速發(fā)展的同時(shí),各種新型的編程技術(shù)猶如雨后春筍般出現(xiàn)。多線程編程技術(shù)在誕生時(shí)就一直受到較高的關(guān)注,并經(jīng)過多方的改進(jìn),確定了POSIX多線程標(biāo)準(zhǔn),并不斷發(fā)展完善[9]。</p><p> 在實(shí)際應(yīng)用中,一個(gè)采用了多線程技術(shù)的應(yīng)用程序可以更好地利用系統(tǒng)資源。其主要優(yōu)勢(shì)在于充分利用了CPU的空閑時(shí)間片,可以用盡可能少的時(shí)間來對(duì)用戶的要求做出響應(yīng),使
11、得進(jìn)程的整體運(yùn)行效率得到較大提高,同時(shí)增強(qiáng)了應(yīng)用程序的靈活性[4]。更為重要的是,由于同一進(jìn)程的所有線程是共享同一內(nèi)存,所以不需要特殊的數(shù)據(jù)傳送機(jī)制,不需要建立共享存儲(chǔ)區(qū)或共享文件,從而使得不同任務(wù)之間的協(xié)調(diào)操作與運(yùn)行、數(shù)據(jù)的交互、資源的分配等問題更加易于解決。多線程數(shù)據(jù)交互采用的是共享內(nèi)存,因而存在互斥與同步操作。POSIX標(biāo)準(zhǔn)提供標(biāo)準(zhǔn)線程庫(kù)pthread。線程庫(kù)中有各種線程同步的方法,這方便了線程間的數(shù)據(jù)交互。</p>
12、<p> 本文在總結(jié)多線程互斥與同步操作的基礎(chǔ)上,設(shè)計(jì)程序測(cè)試多線程數(shù)據(jù)交互的性能。分析在采用多線程進(jìn)行數(shù)據(jù)交互過程中,各種互斥與同步操作的數(shù)據(jù)交互的效率與資源占用情況。對(duì)比各種多線程數(shù)據(jù)交互的方式方法,能為多線程程序設(shè)計(jì)提供良好的參考。</p><p><b> 1.2論文組織</b></p><p> 本文設(shè)計(jì)中以Linux操作系統(tǒng)作為嵌入式系統(tǒng)
13、的研究對(duì)象,分析多線程程序設(shè)計(jì)中各種線程互斥與同步操作,并設(shè)計(jì)程序,測(cè)試多線程數(shù)據(jù)交互的性能,生成總結(jié)報(bào)告。</p><p> 本文主要由四部分組成:</p><p> 第一部分:介紹論文的研究背景、主要內(nèi)容及組織方式。</p><p> 第二部分:總結(jié)多線程數(shù)據(jù)交互中的各種互斥與同步方式,并分析各種方式的實(shí)現(xiàn)過程以及存在的優(yōu)缺點(diǎn)。</p>&l
14、t;p> 第三部分:選取在多線程數(shù)據(jù)交互過程中需要測(cè)試的性能的指標(biāo)以及測(cè)試軟件選擇和基本的操作。</p><p> 第四部分:對(duì)于各種互斥與同步方法設(shè)計(jì)相應(yīng)的測(cè)試程序,觀察測(cè)試結(jié)果,分析產(chǎn)生結(jié)果的原因。在此基礎(chǔ)上設(shè)計(jì)綜合測(cè)試程序,進(jìn)一步分析制約多線程數(shù)據(jù)交互性能的瓶頸。</p><p> 2多線程數(shù)據(jù)交互方法</p><p> 多線程數(shù)據(jù)交互的方法比較
15、成熟,數(shù)量眾多。進(jìn)行多線程編程時(shí),最應(yīng)注意的就是數(shù)據(jù)交互中共享數(shù)據(jù)的問題。因?yàn)闊o法知道哪個(gè)線程會(huì)在哪個(gè)時(shí)候?qū)蚕頂?shù)據(jù)進(jìn)行操作,也無法知道哪個(gè)線程先運(yùn)行,哪個(gè)線程后運(yùn)行。在一般的多線程數(shù)據(jù)交互中,可以將線程看做進(jìn)程來進(jìn)行數(shù)據(jù)間的通信[5][7][9]。當(dāng)然,線程有自己獨(dú)有的多線程數(shù)據(jù)交互的方法,主要有互斥鎖方式、條件變量方式、讀寫鎖方式、線程信號(hào)方式。</p><p> 2.1使用互斥鎖進(jìn)行數(shù)據(jù)交互</p&
16、gt;<p> 2.1.1 互斥鎖基本原理</p><p> 互斥鎖是最基本也是最簡(jiǎn)單的數(shù)據(jù)交互方式?;コ怄i能夠保證數(shù)據(jù)排他性的訪問,確保了數(shù)據(jù)的安全性。不過互斥鎖交互數(shù)據(jù)中,線程之間申請(qǐng)互斥鎖中會(huì)有沖突產(chǎn)生。因而需要在線程解鎖后進(jìn)行延時(shí)。保證其他線程能夠申請(qǐng)到互斥鎖。這降低了線程間通信的效率。影響系統(tǒng)性能[4][7][9][11]。</p><p> 互斥鎖以排他方式
17、防止共享數(shù)據(jù)被并發(fā)修改?;コ怄i是一個(gè)二元變量,其狀態(tài)為開鎖和上鎖狀態(tài)。</p><p> 在訪問共享資源中,首先申請(qǐng)?jiān)摶コ怄i,如果該互斥鎖處于開鎖狀態(tài),則申請(qǐng)到該鎖對(duì)象,并立即占有該資源,以防止其他線程訪問該資源;如果該互斥鎖處于鎖定狀態(tài),默認(rèn)阻塞等待。并且,只有鎖定該互斥鎖的進(jìn)程才能釋放該互斥鎖。其他線程的釋放操作無效。這樣,容易產(chǎn)生死鎖現(xiàn)象,編程時(shí)需要考慮到鎖的各種情況,防止死鎖。</p>&
18、lt;p> 2.1.2互斥鎖數(shù)據(jù)交互方法</p><p> 互斥鎖數(shù)據(jù)交互主要流程包括:使用庫(kù)函數(shù)pthread提供的pthread_mutex_init對(duì)互斥鎖初始化,以此確定互斥鎖的屬性。在讀寫數(shù)據(jù)時(shí),使用函數(shù)pthread_mutex_lock對(duì)互斥鎖上鎖,進(jìn)而能對(duì)數(shù)據(jù)進(jìn)行排他性訪問。當(dāng)對(duì)數(shù)據(jù)運(yùn)算完成后,需要使用函數(shù)pthread_mutex_unlock進(jìn)行解鎖,使其他的線程可以申請(qǐng)到該鎖。最后
19、,當(dāng)使用完成后,需要函數(shù)pthread_mutex_destroy來銷毀互斥鎖。有時(shí),為了避免死鎖情況,可以采用函數(shù)pthread_mutex_trylock來判斷是否上鎖。</p><p> 互斥鎖的操作使用簡(jiǎn)單,能夠?yàn)槎嗑€程間數(shù)據(jù)的交互提供很好的支持。而且,工作過程穩(wěn)定,不需要另外的設(shè)計(jì)算法。是多線程數(shù)據(jù)交互很好的選擇。</p><p> 2.2使用條件變量進(jìn)行數(shù)據(jù)交互</p
20、><p> 2.2.1 條件變量基本原理</p><p> 條件變量是互斥鎖的補(bǔ)充,互斥鎖能夠解決資源的互斥訪問,但互斥鎖一個(gè)明顯的缺點(diǎn)是它只有兩種狀態(tài):鎖定和非鎖定。而條件變量通過允許線程阻塞和等待另一個(gè)線程發(fā)送信號(hào)的方法彌補(bǔ)了互斥鎖的不足,它常和互斥鎖一起使用。條件變量的使用能夠很好的實(shí)現(xiàn)數(shù)據(jù)的交互,在多線程數(shù)據(jù)交互中具有很好的實(shí)用價(jià)值[4][5]。</p><p&
21、gt; 條件變量是互斥鎖的擴(kuò)充,定義一個(gè)條件變量后,需要定義對(duì)應(yīng)的互斥鎖。條件變量被用來阻塞一個(gè)線程,當(dāng)條件不滿足時(shí),線程往往解開相應(yīng)的互斥鎖并等待條件發(fā)生變化。一旦其它的某個(gè)線程改變了條件變量,它將通知相應(yīng)的條件變量喚醒一個(gè)或多個(gè)正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖并重新測(cè)試條件是否滿足[15]。</p><p> 2.2.2 條件變量操作過程</p><p> 使用
22、條件進(jìn)行數(shù)據(jù)交互時(shí),首先,使用函數(shù)pthread_cond_init初始化條件變量,并且要初始化相應(yīng)的互斥鎖。然后鎖定互斥鎖,并調(diào)用函數(shù)pthread_cond_wait阻塞等待條件變量,同時(shí)會(huì)解開互斥鎖。當(dāng)其他線程調(diào)用函數(shù)pthread_cond_signal通知等待該條件變量的第一個(gè)線程時(shí),阻塞取消,線程繼續(xù)執(zhí)行。當(dāng)程序運(yùn)行完后,調(diào)用函數(shù)pthread_cond_destroy銷毀條件變量。也可調(diào)用函數(shù)pthread_cond_ti
23、medwait函數(shù)在指定的時(shí)間內(nèi)阻塞等待條件變量。當(dāng)有多個(gè)線程等待變量時(shí),可以調(diào)用函數(shù)pthread_cond_broadcast函數(shù)通知等待該條件變量的所有線程。</p><p> 條件變量的操作相對(duì)互斥鎖是比較復(fù)雜的,但是能夠完成更多的數(shù)據(jù)交互,并且,由于條件變量采用的是通知等待的模式,因而在數(shù)據(jù)交互處理中更加的方便靈活,效率也比互斥鎖要高。是多線程編程中數(shù)據(jù)交互和同步很好的選擇。</p>&
24、lt;p> 2.3使用讀寫鎖進(jìn)行數(shù)據(jù)交互</p><p> 2.3.1 讀寫鎖基本原理</p><p> 在對(duì)數(shù)據(jù)的讀寫應(yīng)用中,更多的操作是讀操作,而寫操作較少,例如對(duì)數(shù)據(jù)庫(kù)函數(shù)的讀寫應(yīng)用,為了滿足當(dāng)前能夠允許多個(gè)讀寫,但只允許一個(gè)寫入的需求,線程提供了讀寫鎖來實(shí)現(xiàn)。</p><p> 在數(shù)據(jù)交互過程中,如果有其它線程讀數(shù)據(jù),則允許其他線程執(zhí)行讀操作,
25、但不允許寫操作;如果有其它線程寫數(shù)據(jù),則其它線程的讀、寫操作均允許。</p><p> 在讀寫鎖過程中,如果某線程申請(qǐng)了讀鎖,其他線程可以再申請(qǐng)讀鎖,但不能申請(qǐng)寫鎖。如果某線程申請(qǐng)了寫鎖,則其它線程不能申請(qǐng)讀鎖,也不能申請(qǐng)寫鎖。</p><p> 2.3.2 讀寫鎖操作過程</p><p> 在使用讀寫鎖過程中,首先,調(diào)用函數(shù)pthread_rwlock_in
26、it初始化讀寫鎖。當(dāng)需要讀取數(shù)據(jù)時(shí),可以調(diào)用函數(shù)pthread_rwlock_rdlock阻塞申請(qǐng)讀鎖,這個(gè)時(shí)候仍然可以再申請(qǐng)讀鎖,但是不能夠申請(qǐng)寫鎖。在需要寫數(shù)據(jù)的時(shí)候,可以調(diào)用函數(shù)pthread_rwlock_wrlock阻塞申請(qǐng)寫鎖,當(dāng)申請(qǐng)到寫鎖后,就不能再申請(qǐng)到讀鎖,也不能申請(qǐng)寫鎖。在讀寫鎖完成后,可以調(diào)用函數(shù)pthread_rwlock_unlock來釋放鎖,在不需要讀寫鎖后,應(yīng)調(diào)用函數(shù)pthread_rwlock_destr
27、oy來銷毀讀寫鎖。在申請(qǐng)讀寫鎖過程中,可以分別調(diào)用函數(shù)pthread_rwlock_trywrlock和函數(shù)pthread_rwlock_tryrdlock函數(shù)來進(jìn)行非阻塞申請(qǐng)讀鎖和非阻塞申請(qǐng)寫鎖。</p><p> 讀寫鎖是基于實(shí)際操作中的讀多于寫而設(shè)計(jì)的,在多線程數(shù)據(jù)交互中,能夠避免排他性的讀數(shù)據(jù)而影響整體的性能。同時(shí),讀寫鎖也能夠很好的實(shí)現(xiàn)多線程的數(shù)據(jù)交互與同步,具有很好的實(shí)用意義。</p>
28、<p> 2.4其它線程數(shù)據(jù)交互方式</p><p> 2.4.1 信號(hào)量數(shù)據(jù)交互方式</p><p> 信號(hào)量本質(zhì)上是一個(gè)非負(fù)的整數(shù)計(jì)數(shù)器,它被用來控制對(duì)公共資源的訪問。當(dāng)公共資源增加時(shí),調(diào)用函數(shù)sem_post()增加信號(hào)量。只有當(dāng)信號(hào)量值大于0時(shí),才能使用公共資源,使用后,函數(shù)sem_wait()減少信號(hào)量。函數(shù)sem_trywait()和函數(shù)pthread_ mu
29、tex_trylock()起同樣的作用,它是函數(shù)sem_wait()的非阻塞版本。信號(hào)量定義完成了互斥體和條件變量的封裝,按照多線程程序設(shè)計(jì)中訪問控制機(jī)制,控制對(duì)資源的同步訪問,提供程序設(shè)計(jì)人員更方便的調(diào)用接口[12]。</p><p> 2.4.2 線程與信號(hào)數(shù)據(jù)交互方式</p><p> 線程與擁有與信號(hào)相關(guān)的私有數(shù)據(jù)---線程信號(hào)掩碼,這樣,線程可以使用信號(hào)操作來實(shí)現(xiàn)數(shù)據(jù)的同步,
30、每個(gè)線程可也向別的線程發(fā)送信號(hào),每個(gè)線程可以設(shè)置自己的信號(hào)阻塞集合并設(shè)置針對(duì)某信號(hào)的處理方式,但同一進(jìn)程中對(duì)某信號(hào)的處理方式只能有一個(gè)有效,即最后一次設(shè)置的處理方式。如果別的進(jìn)程向當(dāng)前進(jìn)程中發(fā)送一個(gè)信號(hào),那么由哪個(gè)線程處理則是未知的[6][8][13]。</p><p> 3多線程數(shù)據(jù)性能測(cè)試方法</p><p> 多線程數(shù)據(jù)交互中,監(jiān)測(cè)系統(tǒng)的性能能夠很好的了解多線程數(shù)據(jù)交互中系統(tǒng)存在
31、的瓶頸以及采用數(shù)據(jù)交互方法存在的部分問題。在普通的Linux系統(tǒng)監(jiān)測(cè)中,主要包括正在執(zhí)行的進(jìn)程、內(nèi)存的使用率、磁盤的性能、網(wǎng)絡(luò)流量和CPU的壓力。由于多線程數(shù)據(jù)交互中,系統(tǒng)負(fù)載不會(huì)改變,而又不涉及到網(wǎng)絡(luò)和磁盤。因此,選擇CPU性能、內(nèi)存使用率以及正在運(yùn)行的進(jìn)程作為監(jiān)測(cè)的指標(biāo)[12][14][15]。</p><p> 3.1 CPU性能測(cè)試</p><p> CPU是電腦的核心硬件,C
32、PU的使用情況對(duì)程序的設(shè)計(jì)有很好的指導(dǎo)作用。在觀察多線程數(shù)據(jù)交互中,使用top命令來觀察CPU的運(yùn)行。其顯示結(jié)果如圖3.1.1所示。</p><p> 圖3.1.1 top命令運(yùn)行界面</p><p> 在圖中,CPU性能主要觀測(cè)第三行,us表示用戶空間占用CPU百分比,sy表示內(nèi)核空間占用CPU百分比,ni表示用戶進(jìn)程空間內(nèi)改變過優(yōu)先級(jí)的進(jìn)程占用CPU百分比,id表示空閑CPU百分比
33、,wa表示等待輸入輸出的CPU時(shí)間百分比,hi表示硬中斷,si表示軟中斷。</p><p> 在界面第一行中,包含用戶登錄時(shí)間,當(dāng)前用戶數(shù)和系統(tǒng)在一分鐘、五分鐘、十五分鐘內(nèi)的平均負(fù)載。第二行中,包含了系統(tǒng)進(jìn)程總數(shù)、正在運(yùn)行、睡眠、僵尸、停止的進(jìn)程數(shù)。而第四行中,包含物理內(nèi)存總量、使用的物理內(nèi)存總量、空閑物理內(nèi)存總量以及用作內(nèi)核緩存的內(nèi)存量。最后是進(jìn)程信息區(qū),包含了進(jìn)程的ID、父進(jìn)程的ID以及CPU的占用率。&l
34、t;/p><p><b> 3.2內(nèi)存性能測(cè)試</b></p><p> 內(nèi)存是Linux內(nèi)核所有管理的重要資源之一,內(nèi)存管理系統(tǒng)是操作系統(tǒng)中的重要部分。在觀察多線程數(shù)據(jù)交互中,采用free命令來監(jiān)控內(nèi)存使用情況。其界面如圖3.2.1所示。</p><p> 圖3.2.1 free命令界面</p><p> 其中,M
35、em表示物理內(nèi)存統(tǒng)計(jì),包括總共物理內(nèi)存,使用的內(nèi)存,空閑內(nèi)存空間。-/+buffer/cached表示物理內(nèi)存的緩存統(tǒng)計(jì)。Swap表示硬盤上交換分局的使用情況。在多線程數(shù)據(jù)交互中,主要關(guān)注物理內(nèi)存統(tǒng)計(jì)情況。</p><p> 對(duì)于單獨(dú)程序而言,可以使用命令“pmap –x +進(jìn)程ID”來獲得進(jìn)程使用內(nèi)存的情況,輸入命令后,其界面圖如下所示:</p><p> 圖3.2.2 命令pmap
36、界面圖</p><p> 由上圖可以得出,程序two_change總共占用內(nèi)存空間為22196KB。并且,可以了解每一個(gè)Mapping對(duì)應(yīng)映像名的起始地址。是觀察單獨(dú)進(jìn)程內(nèi)存使用情況很好的工具。</p><p><b> 3.3進(jìn)程運(yùn)行測(cè)試</b></p><p> 系統(tǒng)進(jìn)程的運(yùn)行對(duì)于分析系統(tǒng)的各項(xiàng)指標(biāo)具有重要的意義,觀察進(jìn)程對(duì)系統(tǒng)資源的
37、占用能更好的理解多線程數(shù)據(jù)交互過程以及性能。對(duì)于系統(tǒng)進(jìn)程的觀察,采用圖形界面軟件KDE System Guard ,其界面圖如圖3.3.1所示。</p><p> 圖3.3.1 KDE System Guard界面</p><p> 根據(jù)圖形界面顯示,在進(jìn)程表中可以選擇“樹”形顯示,能夠清楚的了解系統(tǒng)進(jìn)程的關(guān)系。在進(jìn)程列表中,可以查看進(jìn)程的狀態(tài)、進(jìn)程ID以及父進(jìn)程等信息。能夠了解線程占
38、用CPU比例??梢院芎玫姆治鼍€程的運(yùn)行情況。</p><p> 由于圖形界面占用較多的系統(tǒng)資源,在觀察程序運(yùn)行中,可以簡(jiǎn)單的使用“ps –all” 命令,得到如下圖所示界面:</p><p> 圖3.3.2 ps命令界面圖</p><p> 從圖中,可以獲得程序two_change的進(jìn)程ID 為7638.這樣,結(jié)合top命令和pmap命令,能夠很容易的獲得進(jìn)程
39、ID為7638所占用的CPU和內(nèi)存等系統(tǒng)資源。方便對(duì)多線程程序的測(cè)試分析。</p><p> 4測(cè)試步驟及結(jié)果分析</p><p> 通過分析多線程數(shù)據(jù)交互的各種方法,在總結(jié)成熟技術(shù)基礎(chǔ)上,設(shè)計(jì)程序,分析程序運(yùn)行結(jié)果,測(cè)試多線程數(shù)據(jù)交互中系統(tǒng)的性能。測(cè)試方法采用ps、top、pmap命令,觀察CPU使用率、內(nèi)存使用率以及進(jìn)程運(yùn)行情況。</p><p> 4.1
40、基于互斥鎖的設(shè)計(jì)思路及測(cè)試結(jié)果</p><p> 4.1.1互斥鎖程序設(shè)計(jì)思路</p><p> 利用互斥鎖進(jìn)行數(shù)據(jù)交互是基于互斥鎖在鎖定后,只有鎖定互斥鎖的線程能夠?qū)?shù)據(jù)進(jìn)行訪問,而其他的線程需要等待線程解鎖后才能進(jìn)行數(shù)據(jù)的訪問。這樣,利用互斥鎖就能完成多線程間數(shù)據(jù)交互,避免沖突。</p><p> 設(shè)計(jì)思路上,首先創(chuàng)建兩個(gè)線程,一個(gè)甲線程用于產(chǎn)生隨機(jī)數(shù)據(jù)并
41、寫入指定文件和賦值給全局變量,另一個(gè)乙線程用于處理甲線程產(chǎn)生的數(shù)據(jù),具體功能圖和程序流程圖如圖4.1.1、4.1.2所示。</p><p> 圖4.1.1 互斥鎖數(shù)據(jù)交互設(shè)計(jì)圖</p><p> 圖4.1.2 互斥鎖程序設(shè)計(jì)流程圖</p><p> 線程甲、乙是并行執(zhí)行。主線程調(diào)用pthread_join()函數(shù)來阻塞等待線程甲、乙結(jié)束。線程甲調(diào)用data_p
42、roduce()函數(shù)來產(chǎn)生隨機(jī)數(shù)據(jù),并且將產(chǎn)生的隨機(jī)數(shù)據(jù)傳遞給全局變量temp。線程乙調(diào)用data_handle()處理數(shù)據(jù),對(duì)全局變量temp的數(shù)據(jù)進(jìn)行數(shù)學(xué)運(yùn)算。整個(gè)數(shù)據(jù)交互過程采用全局變量的方式來傳遞數(shù)據(jù)。部分源程序如下所示。</p><p> 線程甲產(chǎn)生隨機(jī)數(shù)據(jù),并賦值給全局變量,其函數(shù)data_produce()源程序如下:</p><p> void* data_produc
43、e(void*arg)</p><p><b> {</b></p><p><b> int i=0;</b></p><p><b> while(1){</b></p><p> pthread_mutex_lock(&data_mutex);</p
44、><p> temp=rand();</p><p><b> i++;</b></p><p> printf(“%d\n”,i);</p><p> pthread_mutex_unlock(&data_mutex);</p><p><b> sleep(1);<
45、;/b></p><p><b> }</b></p><p><b> }</b></p><p> 數(shù)據(jù)產(chǎn)生函數(shù)是一個(gè)死循環(huán)過程,不停的使用鎖定互斥量data_mutex來對(duì)全局變量temp進(jìn)行排他性訪問。在賦值完成后,再解鎖,并且等待1s中,以便其他線程獲取互斥量而對(duì)數(shù)據(jù)進(jìn)行讀取。</p>
46、<p> 線程乙讀取全局變量數(shù)據(jù),并且進(jìn)行簡(jiǎn)單處理,其函數(shù)data_handle()源程序如下:</p><p> void* data_handle(void*arg)</p><p><b> {</b></p><p> int num,i;</p><p><b> double j
47、;</b></p><p><b> num =0;</b></p><p><b> while(1){</b></p><p> pthread_mutex_lock(&data_mutex);</p><p><b> j=temp;</b>&
48、lt;/p><p><b> num++;</b></p><p> printf("%d\n",num);</p><p> pthread_mutex_unlock(&data_mutex);</p><p> sleep(1); </p><p><b&
49、gt; }</b></p><p><b> }</b></p><p> 在data_handle()函數(shù)中,執(zhí)行的是死循環(huán),不停的讀取數(shù)據(jù)并將全局變量的數(shù)據(jù)進(jìn)行運(yùn)算賦值。而為確保數(shù)據(jù)交互的可靠性,在讀取數(shù)據(jù)前執(zhí)行鎖定互斥量data_mutex的操作。當(dāng)甲線程鎖定互斥量后,乙線程將阻塞等待,同樣,甲線程在乙線程鎖定互斥量后也會(huì)阻塞等待。乙在讀取處理
50、完數(shù)據(jù)后會(huì)解鎖,此時(shí),等待上鎖的甲線程會(huì)立即獲得互斥鎖。這樣就保證了數(shù)據(jù)能夠正確的讀取和處理。</p><p> 4.1.2互斥鎖數(shù)據(jù)交互測(cè)試結(jié)果</p><p> 通過分析程序,在線程乙中,插入變量num,每次處理完數(shù)據(jù)后都進(jìn)行加一操作,并顯示num變量值。同樣,在線程甲中定義變量i,進(jìn)行同樣的操作,程序運(yùn)行結(jié)果如下:</p><p> 圖4.1.3 互斥鎖
51、程序運(yùn)行結(jié)果</p><p> 根據(jù)上圖結(jié)果表明,總會(huì)有兩個(gè)同樣的數(shù)據(jù)顯示,一個(gè)是甲線程中的變量i,一個(gè)是乙線程中的變量num,兩個(gè)線程在各自線程每運(yùn)行一次都會(huì)加一并且打印結(jié)果。因此可知,線程甲、乙交替運(yùn)行,全局變量temp在甲線程賦值后很快被乙線程讀取數(shù)據(jù),在讀取數(shù)據(jù)后,甲線程才再次給temp賦值,整個(gè)實(shí)現(xiàn)過程沒有沖突出現(xiàn)?;コ怄i進(jìn)行數(shù)據(jù)交互中,能夠很好的完成數(shù)據(jù)的交互。</p><p&g
52、t; 采用top命令,觀察進(jìn)程PID為7197的運(yùn)行狀態(tài),即調(diào)試程序的運(yùn)行??芍珻PU占用率為3.0%,內(nèi)存使用了502M。</p><p> 圖4.1.4 互斥鎖測(cè)試程序結(jié)果</p><p> 根據(jù)上述top命令結(jié)果分析,由于互斥鎖操作中,需要等待操作,而等待操作過程中,CPU空閑,因此,CPU的使用率十分的低,調(diào)用pmap命令查看程序運(yùn)行單獨(dú)內(nèi)存,內(nèi)存占用大小為22200KB,
53、說明使用互斥鎖進(jìn)行數(shù)據(jù)交互過程中,對(duì)系統(tǒng)資源占用十分的少,主要占用的是內(nèi)存資源。當(dāng)去掉等待時(shí)間時(shí)。部分源程序如下。</p><p> 甲線程修改后函數(shù)data_produce()源程序如下:</p><p> void* data_produce(void*arg)</p><p><b> {</b></p><p&
54、gt;<b> int i=0;</b></p><p><b> while(1){</b></p><p> for(i=0;i<10000;i++){</p><p> pthread_mutex_lock(&data_mutex);</p><p> sum_temp
55、--;</p><p> pthread_mutex_unlock(&data_mutex);</p><p><b> }</b></p><p><b> temp++;</b></p><p> printf("produce data is %d\n",t
56、emp);</p><p><b> }</b></p><p><b> }</b></p><p> 在修改中,去掉了等待時(shí)間,并且在互斥操作中對(duì)互斥鎖data_mutex進(jìn)行一萬次的重復(fù)操作,并且在解鎖操作后不去等待而直接的進(jìn)行上鎖操作。</p><p> 線程乙數(shù)據(jù)處理函數(shù)data_
57、handle()源程序修改后如下:</p><p> void* data_handle(void*arg)</p><p><b> {</b></p><p> int num,i;</p><p><b> double j;</b></p><p><b
58、> num =0;</b></p><p><b> while(1){</b></p><p> for(i=0;i<10000;i++){</p><p> pthread_mutex_lock(&data_mutex);</p><p> sum_temp++;</p
59、><p> pthread_mutex_unlock(&data_mutex);</p><p><b> }</b></p><p><b> temp++;</b></p><p> printf("handle data is %d\n",temp);</
60、p><p><b> }</b></p><p><b> }</b></p><p> 線程乙處理數(shù)據(jù)也沒有加入等待操作,直接對(duì)互斥量進(jìn)行上鎖和解鎖操作,這樣,在上鎖過程中,甲線程和乙線程上鎖就是隨機(jī)競(jìng)爭(zhēng)的。這不能保證當(dāng)甲線程產(chǎn)生數(shù)據(jù)后,乙線程能夠立即的對(duì)數(shù)據(jù)進(jìn)行處理,相反,甲線程幾乎會(huì)一直占有互斥鎖,而乙線程會(huì)一直的
61、阻塞等待。 </p><p> 運(yùn)行改編后的程序,結(jié)果如下:</p><p> 圖4.1.5 無等待時(shí)間運(yùn)行結(jié)果</p><p> 根據(jù)結(jié)果顯示,線程甲和線程乙在任意一個(gè)占用互斥鎖后,會(huì)一直的占用,并且不停的運(yùn)行,直到下次另一個(gè)線程搶占到互斥鎖。這樣,線程間的數(shù)據(jù)交互就會(huì)出現(xiàn)不同步的問題。這對(duì)數(shù)據(jù)交互來說,是十分危險(xiǎn)的。因此,在使用互斥鎖過程中,插入等待
62、時(shí)間是有必要的。</p><p> 通過調(diào)用top命令,可觀察得到新的檢測(cè)圖如圖4.1.6所示。</p><p> 圖4.1.6 無等待時(shí)間系統(tǒng)狀態(tài)</p><p> 由top命令的監(jiān)測(cè)結(jié)果可知,系統(tǒng)運(yùn)行的在滿負(fù)荷狀態(tài),CPU占用率達(dá)到95.0%,內(nèi)存也使用在滿負(fù)荷狀態(tài),但是,由于沒有系統(tǒng)等待,很多互斥鎖的申請(qǐng)一直由某一個(gè)線程占有,而其它線程阻塞等待。整個(gè)申請(qǐng)
63、搶占互斥鎖是隨機(jī)的過程,存在很大的數(shù)據(jù)交換問題。內(nèi)存占用大小為22196KB。相對(duì)于含有等待時(shí)間的互斥鎖數(shù)據(jù)交互而言,內(nèi)存變化不大,這說明對(duì)于基于互斥鎖的多線程數(shù)據(jù)交互過程,CPU的負(fù)載主要是用于線程內(nèi)部的數(shù)據(jù)處理,而線程間的切換和同步,并不占用過多的CPU資源。</p><p> 4.2基于條件變量的設(shè)計(jì)思路及測(cè)試結(jié)果</p><p> 4.2.1 條件變量程序設(shè)計(jì)思路</p&
64、gt;<p> 基于條件變量的程序設(shè)計(jì)是創(chuàng)建兩個(gè)線程,一個(gè)生產(chǎn)者線程,一個(gè)消費(fèi)者線程。并且定義一個(gè)具有兩個(gè)緩存區(qū)的結(jié)構(gòu)體,生產(chǎn)者線程寫入數(shù)據(jù),消費(fèi)者線程讀取數(shù)據(jù)。通過條件變量和互斥鎖結(jié)合使用,實(shí)現(xiàn)數(shù)據(jù)的交互。具體工作過程如圖4.2.1所示。</p><p> 圖4.2.1 條件變量數(shù)據(jù)交互設(shè)計(jì)圖</p><p> 由圖可知,與基于互斥鎖的數(shù)據(jù)交互相比,基于條件變量的數(shù)據(jù)
65、交互設(shè)計(jì)添加了等待非空、非滿信號(hào)。利用這種機(jī)制,可以很好的實(shí)現(xiàn)數(shù)據(jù)交互中的問題。在具體實(shí)現(xiàn)過程中,定義一個(gè)結(jié)構(gòu)體buffer作為臨時(shí)的緩存區(qū),用put函數(shù)向緩存區(qū)寫入數(shù)據(jù),當(dāng)寫入數(shù)據(jù)完成后,將發(fā)送非空條件變量,當(dāng)寫滿后阻塞等待非滿條件變量;用get函數(shù)讀取臨時(shí)變量,當(dāng)讀取一個(gè)數(shù)據(jù)后,將發(fā)送非滿條件變量,當(dāng)讀取完所有數(shù)據(jù)后阻塞等待非空條件變量。而消費(fèi)者線程循環(huán)調(diào)用get函數(shù),生產(chǎn)者線程循環(huán)調(diào)用put函數(shù)。部分源程序如下。</p>
66、;<p> 臨時(shí)緩存區(qū)結(jié)構(gòu)體buffer定義如下:</p><p> struct prodcons{</p><p> int buffer[BUFFER_SIZE];//生產(chǎn)產(chǎn)品值</p><p> pthread_mutex_t lock;//互斥鎖</p><p> int readpos,writepos;/
67、/讀寫位置</p><p> pthread_cond_t notempty;//非空條件變量</p><p> pthread_cond_t notfull;//非滿條件變量</p><p><b> } ; </b></p><p> struct prodcons buffer;</p>&l
68、t;p> 在buffer結(jié)構(gòu)體中,定義了一個(gè)兩位數(shù)的一維數(shù)組buffer[]作為數(shù)據(jù)緩存區(qū);并且定義了互斥鎖和兩個(gè)條件變量分別表示非空和非滿;為了便于判斷,定義了讀位置和寫位置兩個(gè)變量,表示讀寫數(shù)組的位置。</p><p> 生產(chǎn)者調(diào)用put函數(shù)源程序如下:</p><p> void put(struct prodcons *prod,int data)//輸入產(chǎn)品子函數(shù)&l
69、t;/p><p><b> {</b></p><p> pthread_mutex_lock(&prod->lock);</p><p> while((prod->writepos+1)%BUFFER_SIZE ==prod->readpos){</p><p> printf(&quo
70、t;producer wait for not full \n");</p><p> pthread_cond_wait(&prod->notfull,&prod->lock);</p><p><b> }</b></p><p> prod->buffer[prod->writepo
71、s]=data;</p><p> prod->writepos++;</p><p> if(prod->writepos >= BUFFER_SIZE)</p><p> prod->writepos =0;</p><p> pthread_cond_signal(&prod->notemp
72、ty);</p><p> pthread_mutex_unlock(&prod->lock);</p><p><b> }</b></p><p> 在生產(chǎn)者調(diào)用put函數(shù)后,將隨機(jī)數(shù)據(jù)傳遞給data,并且將定義的緩存區(qū)buffer傳遞給put函數(shù)。進(jìn)入put函數(shù)后,首先判斷buffer是否已滿,當(dāng)buffer已滿后會(huì)阻
73、塞等待,直到消費(fèi)者線程發(fā)送未滿條件變量。收到信號(hào)后,會(huì)向buffer寫入數(shù)據(jù),并且發(fā)送非空條件變量,激活等待非空條件變量的線程。并且改變寫位置變量值。</p><p> 消費(fèi)者調(diào)用get函數(shù)源程序如下:</p><p> int get(struct prodcons *prod)</p><p><b> {</b></p>
74、<p><b> int data;</b></p><p> pthread_mutex_lock(&prod->lock);</p><p> while(prod->writepos == prod->readpos){</p><p> printf("consumer wait
75、 for not empty \n");</p><p> pthread_cond_wait(&prod->notempty,&prod->lock);</p><p><b> }</b></p><p> data = prod->buffer[prod->readpos];<
76、/p><p> prod->readpos++;</p><p> if(prod->readpos >= BUFFER_SIZE){</p><p> prod->readpos =0;</p><p><b> }</b></p><p> pthread_con
77、d_signal(&prod->notfull);</p><p> pthread_mutex_unlock(&prod->lock);</p><p> return data;</p><p><b> }</b></p><p> 在消費(fèi)者調(diào)用get函數(shù)后,與put函數(shù)相似。會(huì)
78、判斷非空并且會(huì)阻塞等待非空信號(hào)。當(dāng)讀取數(shù)據(jù)后,將數(shù)據(jù)返回給消費(fèi)者,并且發(fā)送非滿條件變量。激活等待非滿條件變量的線程。一般情況下,消費(fèi)者與生產(chǎn)者都會(huì)出現(xiàn)阻塞等待情況。</p><p> 4.2.2 條件變量數(shù)據(jù)交互測(cè)試結(jié)果</p><p> 運(yùn)行程序,其結(jié)果如下:</p><p> 圖4.2.2 條件變量程序運(yùn)行結(jié)果</p><p>
79、由結(jié)果分析可知,生產(chǎn)者線程放入一個(gè)數(shù)據(jù)后,消費(fèi)者線程讀取一個(gè)數(shù)據(jù);之后生產(chǎn)者連續(xù)放入兩個(gè)數(shù)據(jù),然后阻塞等待非滿條件變量。當(dāng)消費(fèi)者線程讀取一個(gè)數(shù)據(jù)后,生產(chǎn)者線程接著放入數(shù)據(jù),如此循環(huán),能夠保證生產(chǎn)者消費(fèi)者數(shù)據(jù)交互高效進(jìn)行。</p><p> 通過調(diào)用top命令,觀察程序運(yùn)行情況如圖4.2.3所示。</p><p> 圖4.2.3 條件變量數(shù)據(jù)交互測(cè)試結(jié)果</p><p
80、> 程序運(yùn)行時(shí)CPU占用率占用率很低,內(nèi)存占用大小為22204KB。這說明基于條件變量的多線程數(shù)據(jù)交互對(duì)系統(tǒng)要求很低。主要是對(duì)內(nèi)存資源占用大。</p><p> 4.3基于讀寫鎖與線程信號(hào)的設(shè)計(jì)思路及測(cè)試結(jié)果</p><p> 4.3.1 讀寫鎖程序設(shè)計(jì)思路</p><p> 基于讀寫鎖程序設(shè)計(jì)是創(chuàng)建四個(gè)線程,兩個(gè)讀線程,兩個(gè)寫線程。兩個(gè)寫線程向數(shù)組中
81、寫入數(shù)據(jù),并且分別申請(qǐng)寫鎖,防止寫入數(shù)據(jù)沖突;兩個(gè)讀線程同時(shí)讀取寫入的數(shù)據(jù),并且競(jìng)爭(zhēng)。當(dāng)寫線程申請(qǐng)到寫鎖后讀線程將被阻塞,同時(shí)另一個(gè)寫線程也被阻塞。而申請(qǐng)到讀線程后,另一個(gè)讀線程也可以申請(qǐng)讀鎖,但是寫線程被阻塞。具體功能圖如圖4.3.1所示。</p><p> 圖4.3.1 基于讀寫鎖的程序設(shè)計(jì)</p><p> 程序?qū)崿F(xiàn)方式與互斥鎖實(shí)現(xiàn)方式相似,通過調(diào)用thread_function
82、_read_o()函數(shù)來讀數(shù)據(jù),通過調(diào)用thread_function_write_o()函數(shù)來向緩存數(shù)組寫入數(shù)據(jù)。讀寫操作均需要調(diào)用讀寫鎖來保證共享數(shù)據(jù)能夠?qū)崿F(xiàn)安全訪問。部分源代碼如下所示。</p><p> 寫線程甲函數(shù)thread_function_write_o源程序如下:</p><p> void *thread_function_write_o(void *arg)<
83、;/p><p><b> {</b></p><p> printf(" write thread one try to get lock \n");</p><p> for(;i<WORK_SIZE;i++){</p><p> pthread_rwlock_wrlock(&rw
84、lock);</p><p> printf("this is write one thread ,write the %d position \n",i);</p><p> work_area[i]=rand();</p><p> pthread_rwlock_unlock(&rwlock);</p><p
85、><b> sleep(3);</b></p><p><b> }</b></p><p> pthread_exit(0);</p><p><b> }</b></p><p> 進(jìn)入寫線程后,首先鎖定讀寫鎖,防止其它讀線程或者寫線程修改數(shù)據(jù),然后向緩存數(shù)
86、組寫入數(shù)據(jù),在寫操作完成后,解開讀寫鎖,并且進(jìn)入休眠,將讀寫鎖交給其它線程。在休眠3秒鐘后再次搶占讀寫鎖。</p><p> 讀線程甲的函數(shù)thread_function_write_o源程序如下:</p><p> void *thread_function_read_o(void *arg)</p><p><b> {</b><
87、;/p><p> printf("thread read one try to get lock ,");</p><p> while(i<WORK_SIZE){</p><p> pthread_rwlock_rdlock(&rwlock);</p><p> printf("this is
88、 thread read one\n ");</p><p> printf("the %d position value is %d\n",i,work_area[i]);</p><p> pthread_rwlock_unlock(&rwlock);</p><p><b> sleep(2);</b
89、></p><p><b> }</b></p><p> pthread_exit(0);</p><p><b> } </b></p><p> 讀線程與寫線程操作相似,讀線程可以有多個(gè)同時(shí)申請(qǐng)讀鎖,但是申請(qǐng)到讀鎖后,寫鎖就被阻塞。</p><p> 4
90、.3.2 讀寫鎖數(shù)據(jù)交互測(cè)試結(jié)果</p><p> 運(yùn)行程序,結(jié)果如下所示:</p><p> 圖4.3.2 讀寫鎖程序運(yùn)行結(jié)果</p><p> 由結(jié)果可知,寫線程甲在申請(qǐng)到寫鎖后,向數(shù)組位置0、1寫入數(shù)據(jù),而寫線程乙在之后申請(qǐng)到寫鎖,并向位置2寫入數(shù)據(jù)。讀鎖是同時(shí)進(jìn)行的,當(dāng)寫鎖解鎖后,讀線程甲、乙都可以申請(qǐng)讀線程,并且顯示出寫入的數(shù)據(jù)。不存在讀線程相互阻塞
91、。但是當(dāng)有寫線程申請(qǐng)到寫鎖時(shí),讀線程阻塞,同樣,在有讀線程申請(qǐng)到讀鎖時(shí),寫線程也會(huì)阻塞。這樣,寫入數(shù)組的數(shù)據(jù)能夠保證順序無重復(fù)的寫入,而且能夠被多次讀取。</p><p> 運(yùn)行程序,調(diào)用top命令,得到線程運(yùn)行狀態(tài)如圖4.3.3所示。</p><p> 圖4.3.3 讀寫鎖數(shù)據(jù)交互測(cè)試結(jié)果</p><p> 同樣,基于共享變量的機(jī)制,讀寫鎖占用系統(tǒng)資源也十分
92、的少,程序運(yùn)行過程中CPU、內(nèi)存占用率都十分的低。通過調(diào)用pmap命令,可得程序內(nèi)存占用大小為42688KB。這相對(duì)于互斥鎖與條件變量來說,是兩倍的差距,而這次創(chuàng)建了四個(gè)線程,之前的程序只是創(chuàng)建了兩個(gè)線程,但是CPU的使用率依舊非常的低,這說明,在多線程數(shù)據(jù)交互中,CPU的使用率只是與線程中數(shù)據(jù)運(yùn)算的多少有關(guān),而與線程的多少和數(shù)據(jù)交互多少無關(guān)。但是,內(nèi)存的多少卻是隨著線程的增加而增加。</p><p> 4.4
93、整體數(shù)據(jù)交互方法設(shè)計(jì)思路與測(cè)試結(jié)果</p><p> 4.4.1整體數(shù)據(jù)交互程序設(shè)計(jì)思路</p><p> 在前期設(shè)計(jì)的基礎(chǔ)上,設(shè)計(jì)中采用互斥鎖、條件變量及讀寫鎖綜合設(shè)計(jì)程序。程序設(shè)計(jì)了六個(gè)線程。由生產(chǎn)者線程向緩沖區(qū)寫入數(shù)據(jù),消費(fèi)者線程讀取數(shù)據(jù),并且由兩個(gè)寫線程同時(shí)向數(shù)組中寫入數(shù)據(jù)。同時(shí)兩個(gè)讀線程一起讀取寫入的數(shù)據(jù)。整體流程圖如圖4.1.1所示。</p><p>
94、; 圖4.4.1 整體設(shè)計(jì)圖</p><p> 程序設(shè)計(jì)十分的復(fù)雜,數(shù)據(jù)間交互采用了互斥鎖,條件變量以及讀寫鎖方式。生產(chǎn)者消費(fèi)者線程間采用條件變量進(jìn)行數(shù)據(jù)交互,消費(fèi)者與寫線程間采用互斥鎖進(jìn)行通信,而讀寫線程間采用讀寫鎖進(jìn)行通信。從而保證程序數(shù)據(jù)交互的安全性。部分源程序如下:</p><p> 消費(fèi)者線程函數(shù)get源程序:int get(struct prodcons *prod)&
95、lt;/p><p><b> {</b></p><p><b> int data;</b></p><p> pthread_mutex_lock(&prod->lock);</p><p> while(prod->writepos == prod->readpo
96、s){</p><p> printf("consumer wait for not empty \n");</p><p> pthread_cond_wait(&prod->notempty,&prod->lock);</p><p><b> }</b></p><
97、p> data = prod->buffer[prod->readpos];</p><p> pthread_mutex_lock(&data_mutex);</p><p> temp =data;</p><p> pthread_mutex_unlock(&data_mutex);</p><p&
98、gt; prod->readpos++;</p><p> if(prod->readpos >= BUFFER_SIZE){</p><p> prod->readpos =0;</p><p><b> }</b></p><p> pthread_cond_signal(&
99、prod->notfull);</p><p> pthread_mutex_unlock(&prod->lock);</p><p> return data;</p><p><b> }</b></p><p> 消費(fèi)者線程中,添加了互斥量data_mutex,使用互斥鎖,將產(chǎn)生的數(shù)據(jù)傳
100、遞全局變量temp,互斥鎖能夠很好的保證在向temp寫數(shù)據(jù)與讀數(shù)據(jù)時(shí)不產(chǎn)生沖突。生產(chǎn)者線程與消費(fèi)者線程間數(shù)據(jù)同步采用條件變量方式,可以很好的實(shí)現(xiàn)生產(chǎn)消費(fèi),并且輸出數(shù)據(jù)給其它線程使用數(shù)據(jù)。</p><p> 寫線程甲的函數(shù)thread_function_write_o源程序如下:</p><p> void *thread_function_write_o(void *arg)</
101、p><p><b> {</b></p><p> printf(" write thread one try to get lock \n");</p><p> for(;i<WORK_SIZE;i++){</p><p> pthread_rwlock_wrlock(&rwlo
102、ck);</p><p> printf("this is write one thread ,write the %d position \n",i);</p><p> pthread_mutex_lock(&data_mutex);</p><p> work_area[i]=temp;</p><p>
103、; pthread_mutex_unlock(&data_mutex);</p><p> pthread_rwlock_unlock(&rwlock);</p><p><b> sleep(3);</b></p><p><b> }</b></p><p> pthr
104、ead_exit(0);</p><p><b> }</b></p><p> 寫線程接收數(shù)據(jù),并且將數(shù)據(jù)寫入緩存數(shù)組中。數(shù)據(jù)來自全局變量temp,并且使用互斥鎖,來完成讀寫temp數(shù)據(jù)的安全性。而寫線程與其他讀寫線程間采用讀寫鎖進(jìn)行同步。在寫線程中,還有寫線程乙,與寫線程甲具有相同的作用。寫線程甲乙相互競(jìng)爭(zhēng),向緩存數(shù)據(jù)順序?qū)懭霐?shù)據(jù)。讀線程可以同步讀取寫入數(shù)組的
105、數(shù)據(jù)。</p><p> 4.4.2 整體數(shù)據(jù)交互測(cè)試結(jié)果</p><p> 運(yùn)行程序,結(jié)果如下所示:</p><p> 圖4.4.2 整體程序運(yùn)行結(jié)果</p><p> 根據(jù)結(jié)果顯示,所有線程同步運(yùn)行,但是消費(fèi)者線程首先被非空條件變量阻塞,讀寫線程比生產(chǎn)者線程提前運(yùn)行,造成寫入數(shù)據(jù)0號(hào)位置的值為0。當(dāng)生產(chǎn)者線程執(zhí)行后,消費(fèi)者線程讀取
106、第一個(gè)數(shù)據(jù)。寫線程將數(shù)據(jù)寫入數(shù)組,讀線程讀取顯示數(shù)據(jù)。多線程之間數(shù)據(jù)交按照生產(chǎn)、消費(fèi)、寫入、讀取順序進(jìn)行,數(shù)據(jù)交互十分良好,沒有出現(xiàn)沖突現(xiàn)象。</p><p> 調(diào)用top命令,程序運(yùn)行狀態(tài)如圖4.4.3所示。</p><p> 圖4.4.3 整體數(shù)據(jù)交互測(cè)試結(jié)果</p><p> 根據(jù)結(jié)果顯示,雖然含有七個(gè)線程,并且數(shù)據(jù)交互頻繁,但是程序占用系統(tǒng)資源依然十分
107、的少。CPU占用率和內(nèi)存使用率也很低。程序運(yùn)行很好。使用pmap命令查看內(nèi)存具體使用情況時(shí),內(nèi)存使用大小為63180KB,占用系統(tǒng)資源十分的少。根據(jù)前面的測(cè)試,互斥鎖數(shù)據(jù)交互占用內(nèi)存22196KB、條件變量數(shù)據(jù)交互內(nèi)存占用22204KB、讀寫鎖數(shù)據(jù)交互42688KB。系統(tǒng)內(nèi)存占用情況要少于全部?jī)?nèi)存的簡(jiǎn)單疊加。但是內(nèi)存占用是比較大得。</p><p> 根據(jù)以上分析,多線程數(shù)據(jù)交互過程中,所占用的CPU資源十分的
108、少,然而內(nèi)存空間占用相對(duì)較多。多線程數(shù)據(jù)交互中,要保證數(shù)據(jù)訪問能安全進(jìn)行,就需要線程同步,而線程同步過程中,會(huì)消耗大量的時(shí)間,以至于對(duì)CPU資源的使用較少,同時(shí),線程間的數(shù)據(jù)傳遞是采用共享內(nèi)存的方式進(jìn)行,對(duì)CPU需求較少。然而,對(duì)于內(nèi)存資源,線程間數(shù)據(jù)傳遞會(huì)占用較多的內(nèi)存,這樣,在單純的進(jìn)行多線程數(shù)據(jù)交互時(shí),對(duì)內(nèi)存的要求遠(yuǎn)高于對(duì)CPU的要求。</p><p><b> 5總結(jié)與展望</b>
109、</p><p> Linux的多線程技術(shù)是一項(xiàng)十分前沿的編程技術(shù),而多線程交互數(shù)據(jù)的技術(shù)仍然在探索中,基于ARM的多線程數(shù)據(jù)交互的性能是在分析多線程數(shù)據(jù)交互的基礎(chǔ)上,測(cè)試多線程數(shù)據(jù)交互中,系統(tǒng)的的資源占用情況。</p><p> 在本文的設(shè)計(jì)中,通過測(cè)試分析,多線程數(shù)據(jù)交互的方式主要有互斥鎖方式、條件變量方式、讀寫鎖方式。每一種多線程數(shù)據(jù)交互的方式CPU占用率十分的少,在設(shè)計(jì)對(duì)比過程
110、中,由于要盡量保證單一變量的方式,因此,不能夠在多線程中進(jìn)行頻繁的占用CPU操作。而單一的多線程數(shù)據(jù)交互中,線程間數(shù)據(jù)交互由于要采用同步機(jī)制,則線程間都需要等待同步,這樣的后果是CPU的使用率明顯的降低。這個(gè)問題需要進(jìn)一步的探索。</p><p> 多線程技術(shù)在嵌入式實(shí)時(shí)系統(tǒng)中具有明顯的優(yōu)勢(shì)。線程能夠同步的執(zhí)行,這樣能極大的提高程序的并行性,充分利用多核處理器的資源。由于線程共享進(jìn)程地址空間內(nèi)的所有資源,所以線
111、程之間的通信是很方便的。多個(gè)線程處理不同的任務(wù),增加了程序的并發(fā)性,是程序更高效的執(zhí)行。這些優(yōu)勢(shì)都是多線程技術(shù)得到了很大得重視,而多線程的數(shù)據(jù)交換性能在很大程度上影響系統(tǒng)整體的性能。分析多線程數(shù)據(jù)交換的性能,能在一定程度上解決系統(tǒng)的瓶頸問題,使系統(tǒng)能夠更加高效的運(yùn)行。</p><p> 多線程的數(shù)據(jù)交互技術(shù)仍然需要改進(jìn),在利用線程同步機(jī)制過程中,線程的等待時(shí)間過長(zhǎng),這不利于系統(tǒng)的實(shí)時(shí)性。雖然可以降低等待同步時(shí)間
112、,但是容易產(chǎn)生讀寫數(shù)據(jù)沖突或者數(shù)據(jù)不能有序的讀寫。同時(shí),在使用互斥鎖過程中,當(dāng)出現(xiàn)死鎖問題時(shí),程序就會(huì)處于癱瘓狀態(tài),也很難查找錯(cuò)誤,給編程帶來了很大的難度,這是多線程數(shù)據(jù)交互今后亟待解決的問題。但是整體上,多線程技術(shù)仍然是最具優(yōu)勢(shì)的一項(xiàng)技術(shù),是很有發(fā)展前景的技術(shù)。</p><p> 本文所述工作由于作者水平有限,對(duì)有些問題未能深入探討,錯(cuò)誤與不妥之處在所難免,敬請(qǐng)各位老師和同學(xué)給予批評(píng)和指正。</p>
113、;<p><b> 參考文獻(xiàn)</b></p><p> [1] Gropp W, Thankur R .Thread-safety in an MPI implementation:requirements and analysis[J]. Parrallel Computing, 2007,33(9):595-604</p><p> [2] 路
114、小俊,王在軍. 基于ARM平臺(tái)及嵌入式實(shí)時(shí)操作系統(tǒng)的通信管理機(jī)[J]. 電力系統(tǒng)自動(dòng)化,2007.31(16):94-98</p><p> [3] 張建周,栢嵩. 嵌入式高可靠性通信管理機(jī)的設(shè)計(jì)[J].電力系統(tǒng)自動(dòng)化,2007,31(16):94-98</p><p> [4] 鄭燕飛,余海燕. Linux多線程機(jī)制探討與實(shí)踐[J]. 計(jì)算機(jī)應(yīng)用,2001(1):81-83</
115、p><p> [5] 劉立卿. Linux內(nèi)核源代碼分析[M]. 北京:機(jī)械工業(yè)出版社,2000.505-535</p><p> [6] 鄒治鋒,張曦煌. Linux2.6 進(jìn)程調(diào)度[J]. 嵌入式系統(tǒng)應(yīng)用,2006,24(10):30-31</p><p> [7] 張威 .Linux信號(hào)機(jī)解析[J]. 電腦知識(shí)與應(yīng)用,2006,28(8):30-31<
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 多線程網(wǎng)絡(luò)文件傳輸系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)畢業(yè)論文
- uClinux下的數(shù)據(jù)傳輸與多線程處理.pdf
- linux多線程編程
- 數(shù)據(jù)容錯(cuò)的多核多線程投機(jī)方法研究.pdf
- 多線程數(shù)據(jù)記錄裝置的軟件設(shè)計(jì).pdf
- java多線程編程詳解
- Windows CE下多線程多路播放的設(shè)計(jì).pdf
- 多線程程序數(shù)據(jù)競(jìng)爭(zhēng)靜態(tài)檢測(cè)方法研究.pdf
- POSIX多線程程序中數(shù)據(jù)競(jìng)爭(zhēng)錯(cuò)誤的檢測(cè).pdf
- 基于多線程UI-Model的遠(yuǎn)程實(shí)時(shí)交互教學(xué)系統(tǒng).pdf
- linux操作系統(tǒng)下的多線程編程詳細(xì)解析
- 多線程的內(nèi)存調(diào)度.pdf
- 基于多線程技術(shù)的水泥企業(yè)生產(chǎn)數(shù)據(jù)采集系統(tǒng).pdf
- 基于多線程機(jī)制的數(shù)據(jù)采集系統(tǒng)的實(shí)現(xiàn)設(shè)計(jì).pdf
- 多線程程序數(shù)據(jù)競(jìng)爭(zhēng)檢測(cè)和驗(yàn)證方法研究.pdf
- 不錯(cuò)的delphi多線程編程教程
- 24李后浪實(shí)驗(yàn)五 多線程
- NUMA架構(gòu)下多線程訪存分析系統(tǒng)與實(shí)現(xiàn).pdf
- 多線程環(huán)境下的軟件事務(wù)內(nèi)存模型研究.pdf
- 驗(yàn)證帶有線程動(dòng)態(tài)創(chuàng)建和退出多線程程序.pdf
評(píng)論
0/150
提交評(píng)論