本文摘要:多線程編程面臨巨大挑戰(zhàn),本篇 計算機論文 分析傳統(tǒng)的基于加鎖以及信號量做線程同步的方法已經越來越不適應性能要求;最新的基于無鎖算法的編程技術雖然能夠提升性能,但是實現的過程非常復雜,使得軟件開發(fā)充滿了挑戰(zhàn)性! 電腦編程技巧與維護 》計算機科技
多線程編程面臨巨大挑戰(zhàn),本篇計算機論文分析傳統(tǒng)的基于加鎖以及信號量做線程同步的方法已經越來越不適應性能要求;最新的基于無鎖算法的編程技術雖然能夠提升性能,但是實現的過程非常復雜,使得軟件開發(fā)充滿了挑戰(zhàn)性。《電腦編程技巧與維護》計算機科技論文發(fā)表期刊,雜志1994年在北京市創(chuàng)刊,所刊內容多以電腦編程實例解析為主題,展示項目開發(fā)和應用編程新思路、新方法及其編程的經驗和技巧,還有計算機領域科學研究、工程技術與應用學術的論文和研究報告等。
摘要:隨著硬件性能的提高,多線程編程技術已經成為軟件業(yè)的主流。文章首先介紹多線程編程所面臨的挑戰(zhàn),其次介紹ZeroMQ消息中間件可以如何應對該問題,并對其中的兩項關鍵技術做了分析,最后對采用ZeroMQ與傳統(tǒng)方法下多線程編程的性能進行對比。
關鍵詞:ZeroMQ;多線程編程;阻塞;無鎖編程
1、多線程編程的挑戰(zhàn)
自摩爾定律提出以來,CPU主頻一直以指數級的速度在增長。為了充分利用硬件性能,改善程序體驗,軟件業(yè)廣泛采用了多線程編程技術。但是由于多個線程是動態(tài)運行的,使得這類程序的編寫和調試異常困難[1-2]。與單線程程序相比,軟件開發(fā)人員往往需要付出數十倍的精力。近幾年,隨著CPU主頻逐漸逼近物理極限,芯片工業(yè)逐步向多核發(fā)展,但新增加的CPU性能無法全面發(fā)揮出來。除了像Erlang[3]這樣的少數語言外,絕大多數編程語言,包括C和C++,并沒有提供對于并發(fā)編程的支持。在傳統(tǒng)多線程編程技術中,采用加鎖以及信號量的方式來實現線程同步。這樣的方式存在如下一些問題:(1)編寫以及維護這類代碼代價非常高昂。根據經驗估算,編寫多線程代碼的成本是編寫單線程代碼成本的10~100倍;(2)這類方法很難擴展到更多線程。大多數多線程應用使用2個線程(例如典型的生產者消費者線程),有一些會用到3個或者4個。
這表明對于一個有著16個或者更多核心的CPU,其硬件性能沒有充分利用起來;(3)即便代碼是多線程的,它往往也不能受益于多核CPU,因為不同的線程間經常彼此阻塞。開發(fā)者很難發(fā)現精巧的多線程程序實際上已經退化成了一個單線程;(4)即便在最理想的情況下,應用程序被設計成避免大范圍使用加鎖操作,還是很難擴展到超過10個核心的CPU上。隨著線程數以及CPU核數的增加,硬件資源的利用率會急劇下降;(5)線程被換入CPU中會引發(fā)程序的上下文切換,以及CPU緩沖區(qū)中的內容失效,這也將極大地影響整個程序的執(zhí)行效率。為了避免加鎖導致的阻塞,最新的編程理論提出了無鎖算法來實現數據共享。該算法需要用到硬件指令集中的“比較以及交換原子操作”[4]來避免加鎖。為了達到無鎖編程的準確性以及安全性,程序員需要具備硬件以及編譯器方面的知識背景。無鎖編程技術雖然提高了軟件性能,但是其高度復雜性使得軟件開發(fā)過程充滿了挑戰(zhàn),所以這樣的技術目前并沒有獲得廣泛的使用。
2、ZeroMQ消息中間件技術
ZeroMQ是由iMatix公司開發(fā)的一款開源的消息中間件。最初的設計目標是在股票交易系統(tǒng)中實現極快的數據交換,所以性能是設計的首要考慮因素。ZeroMQ看起來像是一套嵌入式的網絡鏈接庫,但工作起來更像是一個并發(fā)式的框架。它可以在多種協(xié)議中傳輸消息,如線程間、進程間、TCP、廣播等。開發(fā)人員可以據此構建多種連接模式,如:發(fā)布-訂閱、任務分發(fā)、請求-應答等。它對幾乎所有主流語言均可支持,并能在幾乎所有的操作系統(tǒng)上運行。ZeroMQ目前已經在很廣泛的范圍內獲得使用,包括:金融服務、游戲開發(fā)、嵌入式系統(tǒng)、科學研究,以及航天系統(tǒng)中。為了達到高性能,ZeroMQ采用了兩項核心技術來實現高效的消息傳輸,分別為并發(fā)模型和無鎖隊列。
2.1ZeroMQ的并發(fā)模型
為了充分利用CPU的多核特性,ZeroMQ被設計成完全避免使用鎖,從而使得每個線程能夠全速運行。線程之間的通信采用基于事件的異步消息發(fā)送模式,即經典的參與者模式。它為每一個CPU核啟動一個工作線程,從而避免了當兩個線程共享一個核時所做的線程上下文切換操作(見圖1)。ZeroMQ的內部對象緊密地與特定工作線程綁定到一起。這樣就不需要使用任何臨界區(qū)、鎖,以及信號量等同步操作。并且每個ZeroMQ內部對象與特定的CPU核也是關聯(lián)的,這樣也避免了上下文切換,有效利用CPU緩存區(qū)機制。這種設計避免了傳統(tǒng)多線程開發(fā)所面臨的諸多問題,因為線程之間不再需要共享對象。不過在該設計中,需要提供一個調度器。調度器采用基于事件驅動的方式管理ZeroMQ內部對象,從而避免了在整個循環(huán)中去檢測對象,也避免了對象長時間地占用CPU這種情況。這樣,整個系統(tǒng)工作在異步模式下,所有的對象以狀態(tài)機的方式運行。
2.2ZeroMQ的無鎖隊列
為了保證并發(fā)操作,ZeroMQ使用了無鎖隊列在用戶線程以及ZeroMQ工作線程之間交換數據。無鎖隊列中用到無鎖算法,該算法不依賴操作系統(tǒng)所提供的鎖以及信號量等機制實現數據共享,但是需要依賴CPU提供的原子操作。無鎖算法本質上并不是“無鎖”的,只是它的鎖是在硬件層面上實現。此外,無鎖隊列的兩個特別設計使得其擁有很高的性能。第一個特點是:每個隊列對應一個寫線程和一個讀線程(見圖2)。在一個寫線程對應多個讀線程的通信環(huán)境下,ZeroMQ將創(chuàng)建多個隊列。這種讀寫之間一一對應的模式,加上無鎖操作,使得無鎖隊列的實現非常高效。第二個特點是:采用批處理的方法來寫入或者讀取消息。雖然無鎖編程算法比傳統(tǒng)的基于信號量的算法更高效,但是CPU的原子操作很費時,特別是當CPU的多個核之間存在競爭時。為了解決這個問題,ZeroMQ采用了批處理的方法來應對。假設從網絡上收到了一個數據包,其中包含了10個小消息。為了將這些消息寫入無鎖隊列中去,需要使用10次原子操作。ZeroMQ采用的方式是,先將單個消息保存到一個預寫區(qū)域中,累積到一定數目后,使用一次原子操作,一起寫入隊列中;類似地,在讀取時也應用了預讀取緩沖區(qū)。
3、ZeroMQ性能驗證
3.1測試方法
通過對ZeroMQ工作原理的分析,知道其性能無疑會超過傳統(tǒng)多線程方法的。但是這樣的性能差距到底有多大,需要通過實驗來分析。ZeroMQ作為消息中間件可以在多種應用場合傳遞消息。其中的線程間通信模式,使得其可以很好地用于多線程應用程序。在其多種消息傳遞模型中,任務分發(fā)的消息模式特別適合典型的生產者-消費者這種應用形式。傳統(tǒng)多線程編程方法采用了互斥鎖以及信號量來實現生產者-消費者線程之間的數據共享。每一個生產者線程與一個消費者線程作為一個線程對。線程的執(zhí)行時間以生產者線程開始工作,到消費者線程處理完最后一個數據之間的時間間隔作為該線程對的執(zhí)行時間。多線程情況下,將各個線程對的執(zhí)行時間做相加處理。在每次測試期間,指定采用ZeroMQ的方法與采用傳統(tǒng)多線程的方法這兩種程序所處理的消息數是相等的。對不同條件下的執(zhí)行時間進行統(tǒng)計,從而比較哪種方法性能更優(yōu)。
3.2性能分析
通過測試,分別采用兩種方法的多線程程序所用的時間如表1所示。表1中的數據是在一個采用了超線程技術的2核i5CPU上執(zhí)行結果。從表1中可以看出,采用ZeroMQ的多線程編程方法比采用傳統(tǒng)的方法在各種情況下性能均占優(yōu)勢,這表明其對于并發(fā)編程有更好的支持。此外,在與其他主流消息隊列,比如:RabitMQ、ActiveMQ以及MSMQ的性能比較中,ZeroMQ也大幅勝出?紤]到ZeroMQ在軟件開發(fā)以及調試上的便利性,采用其進行多線程軟件開發(fā)將帶來巨大的成本優(yōu)勢。
4、結語
隨著CPU內核數越來越多,如何有效地發(fā)揮硬件運算能力成為越來越重要的任務。ZeroMQ這一消息中間件很好地彌補了性能與易用性之間的鴻溝,使得普通開發(fā)人員也可以編寫出高性能、可靠的軟件產品。
轉載請注明來自發(fā)表學術論文網:http:///dzlw/14707.html