專利名稱::并發(fā)非阻塞無鎖隊(duì)列及其實(shí)施方法和裝置的制作方法
技術(shù)領(lǐng)域:
:本發(fā)明一般地涉及數(shù)字?jǐn)?shù)據(jù)處理領(lǐng)域。具體而言,本發(fā)明涉及利用處理器同步原語如加載鏈接/條件存儲(load-linked/storeconditional,LL國SC)的并發(fā)非阻塞無鎖(non-blocking,lockfree)先進(jìn)先出(FIFO)隊(duì)列。
背景技術(shù):
:在二十世紀(jì)后半葉,開始出現(xiàn)了稱之為信息革命的現(xiàn)象。盡管信息革命是在范圍上比任一事件或者機(jī)器都更廣泛的歷史性發(fā)展,但是沒有哪個(gè)設(shè)備比數(shù)字電子計(jì)算機(jī)更能代表信息革命。毋庸置疑,計(jì)算機(jī)系統(tǒng)的發(fā)展已經(jīng)是一場革命。年復(fù)一年,計(jì)算機(jī)系統(tǒng)增長更快、存儲更多數(shù)據(jù)并提供更多應(yīng)用給它們的用戶。現(xiàn)代計(jì)算機(jī)系統(tǒng)通常包括至少一個(gè)中央處理單元(CPU)以及為了存儲、獲取和傳送信息而必需的支持硬件如通信總線和存儲器。它也包括為了與外界通信而必需的硬件如輸入/輸出控制器或者存儲控制器以及與之附接的設(shè)備如鍵盤、監(jiān)視器、磁帶驅(qū)動器、磁盤驅(qū)動器、耦合到網(wǎng)絡(luò)的通信線路等。該一個(gè)或者多個(gè)CPU是該系統(tǒng)的核心。它們執(zhí)行如下指令,這些指令包括計(jì)算機(jī)程序并指引其它系統(tǒng)組件的操作。通常通過增加并行性并且具體通過利用多個(gè)CPU(也稱為處理器)來提高計(jì)算機(jī)系統(tǒng)的整體速度。在集成電路芯片上封裝各個(gè)處理器的成本并不高,這已經(jīng)使多處理器系統(tǒng)成為現(xiàn)實(shí),雖然這樣的多個(gè)處理器給系統(tǒng)增添了多重的復(fù)雜性。從計(jì)算機(jī)硬件的觀點(diǎn)來看,多數(shù)系統(tǒng)以基本上相同的方式操作。處理器能夠執(zhí)行很簡單的操作,比如算術(shù)、邏輯比較以及將數(shù)據(jù)從一個(gè)位置移動到另一位置。但是各操作執(zhí)行得都很快。處于多個(gè)級別上的復(fù)雜軟件指引計(jì)算機(jī)執(zhí)行為數(shù)眾多的這些簡單操作,使計(jì)算機(jī)能夠執(zhí)行復(fù)雜任務(wù)。通過使用具有增強(qiáng)功能的軟件以及更快的硬件來執(zhí)行基本上相同的一組很簡單的操作,使得被用戶認(rèn)為是計(jì)算機(jī)系統(tǒng)的新功能或者改進(jìn)功能的那些功能成為可能。先進(jìn)先出(FIFO)隊(duì)列廣泛地用于并行應(yīng)用和操作系統(tǒng)中。應(yīng)用和進(jìn)程線程頻繁地使數(shù)據(jù)入列到FIFO隊(duì)列上以及使數(shù)據(jù)從FIFO隊(duì)列中出列。一般而言,F(xiàn)IFO隊(duì)列是如下數(shù)據(jù)結(jié)構(gòu),該數(shù)據(jù)結(jié)構(gòu)提供了包含數(shù)據(jù)的不同存儲器位置的有序列表。隊(duì)列的各不同存儲器位置通常稱為"節(jié)點(diǎn)"。為了使節(jié)點(diǎn)保持有序,各節(jié)點(diǎn)具有"next"指針,該指針標(biāo)識(即指向)隊(duì)列中下一節(jié)點(diǎn)的存儲器位置。隊(duì)列的第一個(gè)節(jié)點(diǎn)稱為"頭節(jié)點(diǎn)"而隊(duì)列的最后一個(gè)節(jié)點(diǎn)稱為"尾節(jié)點(diǎn)"。由于尾節(jié)點(diǎn)是隊(duì)列的最后一個(gè)節(jié)點(diǎn),所以尾節(jié)點(diǎn)的"next"指針通常為NULL(空)。隊(duì)列具有標(biāo)識(即指向)頭節(jié)點(diǎn)的頭指針以及標(biāo)識(即指向)尾節(jié)點(diǎn)的尾指針。通過在隊(duì)列的當(dāng)前尾節(jié)點(diǎn)之后插入節(jié)點(diǎn)來使該節(jié)點(diǎn)入列,使得入列的節(jié)點(diǎn)變成隊(duì)列的新尾節(jié)點(diǎn)。因而,為了使節(jié)點(diǎn)入列到隊(duì)列上,線程必須確定哪個(gè)節(jié)點(diǎn)是當(dāng)前尾節(jié)點(diǎn)。為了實(shí)現(xiàn)這一點(diǎn),線程通常利用隊(duì)列的尾指針。在隊(duì)列的頭部使節(jié)點(diǎn)出列,使得當(dāng)前頭節(jié)點(diǎn)出列而下一節(jié)點(diǎn)變成隊(duì)列的新頭節(jié)點(diǎn)。因而,為了使節(jié)點(diǎn)從隊(duì)列中出列,線程必須確定哪個(gè)節(jié)點(diǎn)是當(dāng)前頭節(jié)點(diǎn)。為了實(shí)現(xiàn)這一點(diǎn),線程通常利用隊(duì)列的頭指針。如上所述,應(yīng)用和進(jìn)程線程在FIFO隊(duì)列上使數(shù)據(jù)入列和出列。多個(gè)不同的此類線程可以進(jìn)行對隊(duì)列的并發(fā)使用。隊(duì)列的并發(fā)使用使得難以維持隊(duì)列的完整性。然而,必須針對隊(duì)列可能遇到的所有可能條件來維持隊(duì)列的完整性。必須使得并發(fā)訪問同步以維持隊(duì)列的完整性。用于包括FIFO隊(duì)列的并發(fā)數(shù)據(jù)結(jié)構(gòu)的算法是阻塞或者非阻塞的。阻塞算法使得緩慢或者延遲的進(jìn)程(或者線程)可以不確定地防止更快的進(jìn)程(或者線程)完成對并發(fā)數(shù)據(jù)結(jié)構(gòu)的操作。非阻塞算法保證了如果一個(gè)或者多個(gè)激活進(jìn)程(或者線程)試圖執(zhí)行對并發(fā)數(shù)據(jù)結(jié)構(gòu)的操作則一些操作將在有限數(shù)目的步驟內(nèi)完成。非阻塞算法通常比阻塞算法更為優(yōu)選,因?yàn)楫?dāng)由于發(fā)生比如處理器調(diào)度搶先、頁面故障和高速緩存未命中這樣的事件而暫?;蛘哐舆t進(jìn)程(或者線程)時(shí),阻塞算法會不利地經(jīng)歷明顯的性能下降。已經(jīng)針對包括并發(fā)FIFO隊(duì)列的共享數(shù)據(jù)結(jié)構(gòu)提出了無鎖算法。無鎖算法使得可以對共享數(shù)據(jù)結(jié)構(gòu)進(jìn)行并發(fā)更新而無需牽涉到由被操作系統(tǒng)管理的鎖來保護(hù)的關(guān)鍵部分。無鎖同步的一些最普遍益處包括比基于鎖的算法更高效;提高了多處理器機(jī)器上的可伸縮性;可用于幾乎所有包括中斷句柄的環(huán)境中;非阻塞實(shí)施自然地避免了優(yōu)先級反轉(zhuǎn);協(xié)作技術(shù)保證了完成進(jìn)度,這不同于無效(u叩roductive)的自旋鎖。特殊處理器同步原語如傳統(tǒng)的比較和交換以及現(xiàn)代的加載鏈接/條件存儲(例如PowerPCldarx/stdcx)已經(jīng)用來為FIFO隊(duì)列和后進(jìn)先出(LIFO)隊(duì)列(LIFO隊(duì)列也稱為LIFO棧)實(shí)施高效的無鎖算法。并發(fā)LIFO隊(duì)列很容易實(shí)施;然而高效的并發(fā)FIFO隊(duì)列明顯地更具^L戰(zhàn)性。Michael等人在1996年的分布式計(jì)算原理研討會上在"簡單、快速和實(shí)用的非阻塞和阻塞并發(fā)算法,,("Simple,Fast,andPracticalNon-blockingandBlockingConcurrentAlgorithms",SymposiumofPrinciplesofDistributedComputing,1996)—文中描述了一種高效的現(xiàn)有技術(shù)并發(fā)隊(duì)列。Michael等人的公開內(nèi)容所存在的問題包括為入列到隊(duì)列中的各用戶節(jié)點(diǎn)分配分離的鏈接節(jié)點(diǎn)。由此,節(jié)點(diǎn)并不直接入列到隊(duì)列中,因?yàn)樾枰~外的鏈接節(jié)點(diǎn)。這會限制隊(duì)列性能以及線程可以使用隊(duì)列的方式。由于存儲器分配問題,分配這一額外鏈接節(jié)點(diǎn)增添了開銷并且使這一算法對于中斷句柄而言不可行。傳統(tǒng)的比較和交換原語需要特殊考慮(例如唯一編號生成器)以防止經(jīng)典的ABA問題(下文將加以討論),這增添了附加開銷。一般而言,當(dāng)進(jìn)程或者線程讀取在如FIFO隊(duì)列之類的共享存儲器位置上的值丄計(jì)算新的值、然后嘗試如比較和交換原語之類的操作時(shí),會出現(xiàn)本領(lǐng)域公知的"ABA問題",如果在讀取與比較和交換之間,一個(gè)或者多個(gè)其它進(jìn)程將值^改變成值仏然后再次改變回值」,則該問題即使不應(yīng)當(dāng)繼續(xù)卻仍然可能繼續(xù)。Michael等人的公開內(nèi)容描述了一種并發(fā)非阻塞隊(duì)列,其中通過將額外"計(jì)數(shù)"字段分配給隊(duì)列指針如尾節(jié)點(diǎn)的"next"指針來解決ABA問題。由此,例如,每當(dāng)任何線程修改尾節(jié)點(diǎn)時(shí),與尾節(jié)點(diǎn)的"next"指針相關(guān)聯(lián)的計(jì)數(shù)將遞增。在ABA問題會以別的方式出現(xiàn)的情形下,如果已經(jīng)在另一節(jié)點(diǎn)上使尾節(jié)點(diǎn)入列和出列,則嘗試使新節(jié)點(diǎn)入列到隊(duì)列上的線程將認(rèn)識到被它認(rèn)為是尾節(jié)點(diǎn)的節(jié)點(diǎn)的"next"指針"計(jì)數(shù)"字段已經(jīng)改變,即使"next"指針仍然具有與以前相同的值。因此,線程將不完成它的入列操作,由此防止出現(xiàn)ABA問題,但代價(jià)是為提供額外"計(jì)數(shù)"字段而必需的附加開銷。于2005年5月3日授權(quán)給Forin等人而轉(zhuǎn)讓給微軟公司的題為"NON-BLOCKINGCONCURRENTQUEUESWITHDIRECTNODEACCESSBYTHREADS"(可由線程進(jìn)行直接節(jié)點(diǎn)訪問的非阻塞并發(fā)隊(duì)列)的美國專利第6,889,269號至少部分地解決了Michael等人公開內(nèi)容中的一些問題,但卻引入了出列時(shí)間窗。Forin等人的專利所存在的問題包括有利地使用戶節(jié)點(diǎn)直接入列到隊(duì)列中而無需額外鏈接節(jié)點(diǎn);然而必須反復(fù)地使虛節(jié)點(diǎn)出列和重新入列,由此增添了明顯開銷。例如,如果平均隊(duì)列深度(AQD)是2個(gè)用戶節(jié)點(diǎn),則所有入列的25%將是無效的虛節(jié)點(diǎn),或者具有1:2的比率。一般而言,虛節(jié)點(diǎn)入列與用戶節(jié)點(diǎn)入列的比率是LAQD(例如1:2、1:3、1:4...)。改進(jìn)了針對ABA問題的解決方案;然而需要隊(duì)列特有編號用來唯一地標(biāo)識包含節(jié)點(diǎn)的隊(duì)列。當(dāng)僅使單個(gè)用戶節(jié)點(diǎn)入列時(shí)隊(duì)列節(jié)點(diǎn)中的時(shí)間窗錯(cuò)誤地檢測到空隊(duì)列。也就是說,如果第一線程暫時(shí)地使虛節(jié)點(diǎn)出列而留下單個(gè)用戶節(jié)點(diǎn),則第二線程上的出列將觀察到空隊(duì)列。這可能造成一些應(yīng)用不正確;也運(yùn)4亍。雖然Forin等人的專利聲明該發(fā)明涉及了利用非阻塞原子比較和交換(CAS)指令的FIFO隊(duì)列,但是在該專利中沒有描述或者在它的流程圖中沒有利用CAS指令。將需要一些附加的存儲排序防護(hù)(storageorderingfence)以在弱一致性處理器上運(yùn)行Forin等人的專利中公開的算法(下文將加以討論)。對更快速處理器的開發(fā)促成了弱一致性處理器架構(gòu)的創(chuàng)建,該架構(gòu)允許一定數(shù)量的指令推測(比如分支推測)和指令的無序執(zhí)行。為了實(shí)現(xiàn)這些類型的執(zhí)行,當(dāng)在組內(nèi)的指令之間不存在依賴性時(shí)處理器,將一系列指令分配給該組。能夠并行或者無序地(即在更早的指令之前執(zhí)行更遲的指令)執(zhí)行組內(nèi)的指令。然而,特別是對于加載和存儲指令,由于指令序列內(nèi)的數(shù)據(jù)依賴性,必須按程序順序執(zhí)行不同組中的指令以獲得正確的處理結(jié)果。因此,將需要附加的存儲排序防護(hù)以在弱一致性處理器上運(yùn)行比如Forin等人的專利中公開的算法這樣的算法。然而,F(xiàn)orin等人的專利沒有詳述為使它的算法可在弱一致性處理器上工作而必需的附加存儲排序防護(hù)(fencing)。使用并發(fā)LIFO隊(duì)列(棧)作為丟棄(dropoff)隊(duì)列也并非很不尋常;然而,在能夠執(zhí)行正常有序任務(wù)處理之前,LIFO隊(duì)列必須轉(zhuǎn)換成FIFO隊(duì)列。例如,于1997年9月23日授權(quán)給Rakity等人而轉(zhuǎn)讓給蘋果計(jì)算機(jī)公司的題為"METHODANDAPPARATUSFORATOMICALLYACCESSINGAQUEUEINAMEMORYSTRUCTUREWHERELIFOISCONVERTEDTOFIFO"(用于在LIFO被轉(zhuǎn)換成FIFO的情況下原子性地訪問存儲器結(jié)構(gòu)中的隊(duì)列的方法和裝置)的美國專利第5,671,446號公開了這樣一種方式。此方式具有很多缺點(diǎn)就性能而言將LIFO隊(duì)列轉(zhuǎn)換成FIFO隊(duì)列可能是昂貴的。在能夠使單個(gè)節(jié)點(diǎn)出列之前,LIFO隊(duì)列中的所有節(jié)點(diǎn)必須轉(zhuǎn)換成FIFO順序。單個(gè)任務(wù)必須執(zhí)行LIFO到FIFO轉(zhuǎn)換。在多處理器系統(tǒng)上這一轉(zhuǎn)換可能變成瓶頸。因此,需要一種用于提供并發(fā)非阻塞無鎖FIFO隊(duì)列的增強(qiáng)的機(jī)制。
發(fā)明內(nèi)容根據(jù)本發(fā)明的優(yōu)選實(shí)施例,僅當(dāng)有必要防止隊(duì)列變空時(shí)才使虛節(jié)點(diǎn)入列到并發(fā)非阻塞無鎖FIFO隊(duì)列中。僅在出列操作過程中并且僅當(dāng)在該出列操作過程中隊(duì)列包含單個(gè)用戶節(jié)點(diǎn)時(shí),虛節(jié)點(diǎn)才入列。這相對于總是將虛節(jié)點(diǎn)保持于隊(duì)列中的常規(guī)機(jī)制而言減少了開銷。用戶節(jié)點(diǎn)直接入列到隊(duì)列中并且能夠按照任何線程的要求立即出列。優(yōu)選地,入列和出列操作包括使用加載鏈接/條件存儲(LL/SC)同步原語。這解決了ABA問題而無需使用唯一編號如隊(duì)列特有編號(queue-specificnumber),并且與包括4吏用比較和交換(CAS)同步原語以及通過使用唯一編號來解決ABA問題的常規(guī)機(jī)制形成對比。此外,優(yōu)選地插入存儲排序防護(hù)以使得算法可以在弱一致性處理器上運(yùn)行。根據(jù)如附圖中所示對本發(fā)明優(yōu)選實(shí)施例的如下具體描述,本發(fā)明的前述以及其它特征和優(yōu)點(diǎn)將變得明顯。下文將結(jié)合附圖來描述本發(fā)明的優(yōu)選示例性實(shí)施例,在附圖中相似的標(biāo)號指代相似的單元。圖1是根據(jù)本發(fā)明優(yōu)選實(shí)施例用于提供并發(fā)、非阻塞、無鎖FIFO隊(duì)列的計(jì)算機(jī)系統(tǒng)的框圖。圖2是根據(jù)本發(fā)明優(yōu)選實(shí)施例的FIFO隊(duì)列的初始狀態(tài)的框圖。圖3圖示了根據(jù)本發(fā)明優(yōu)選實(shí)施例的入列操作的框圖,其中使用戶節(jié)點(diǎn)入列到圖2中所示FIFO隊(duì)列的初始狀態(tài)。圖4A、圖4B和圖4C是共同圖示了根據(jù)本發(fā)明優(yōu)選實(shí)施例的出列操作的框圖。在圖4A中,使虛節(jié)點(diǎn)從圖3中所示狀態(tài)下的FIFO隊(duì)列中出列。在圖4B中,使虛節(jié)點(diǎn)重新入列到圖4A中所示狀態(tài)下的FIFO隊(duì)列中。在圖4C中,使用戶節(jié)點(diǎn)從圖4B中所示狀態(tài)下的FIFO隊(duì)列中出列。圖5是用來圖示根據(jù)本發(fā)明優(yōu)選實(shí)施例的Queue類和Node結(jié)構(gòu)的數(shù)據(jù)布局的示例性偽代碼的示圖。圖6是用來圖示在圖5的Queue類中聲明的入列函數(shù)的示例性偽代碼的示圖。圖7是用來圖示在圖5的Queue類中聲明的enqueueStep2函數(shù)的示例性偽代碼的示圖。圖8是用來圖示在圖5的Queue類中聲明的出列函數(shù)的示例性偽代碼的示圖。圖9是用來圖示在圖5的Queue類中聲明的enqueueDummy函數(shù)的示例性偽代碼的示圖。具體實(shí)施例方式1.0概述根據(jù)本發(fā)明的優(yōu)選實(shí)施例,使用標(biāo)準(zhǔn)的加載鏈接/條件存儲(LL/SC)同步原語來實(shí)施并發(fā)非阻塞無鎖FIFO隊(duì)列。使用加載鏈接/條件存儲同步原語而不是比較和交換(CAS)同步原語解決了ABA問題而無需某一種唯一編號如隊(duì)列特有編號,并且實(shí)現(xiàn)了更高效的定制代碼。因而,本發(fā)明的優(yōu)選實(shí)施例與包括使用比較和交換同步原語以及通過使用唯一編號來解決ABA問題的常規(guī)機(jī)制形成對比。另外,通過對加載鏈接/條件存儲同步原語的謹(jǐn)慎使用,能夠生成更高效的代碼。優(yōu)選地,根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法謹(jǐn)慎地使用插入式存儲排序防護(hù)(例如PowerPC同步指令)以在弱一致性處理器上實(shí)現(xiàn)既高效又正確的執(zhí)行。根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法是協(xié)作型的。如果入列落在后面,則后續(xù)的入列或者出列操作將幫助完成當(dāng)前入列。入列是兩步驟的過程1.將新節(jié)點(diǎn)連接到隊(duì)列的末尾。2.將隊(duì)列的尾指針更新為指向新節(jié)點(diǎn)。如果當(dāng)前入列落在后面,例如當(dāng)前入列被更高優(yōu)先級的任務(wù)搶先或者在上述步驟1與步驟2之間出現(xiàn)頁面故障,則后續(xù)的入列或者出列操作能夠?yàn)楫?dāng)前入列完成步驟2。使用虛節(jié)點(diǎn)來實(shí)現(xiàn)并發(fā)入列和出列操作是本領(lǐng)域中公知的技術(shù);然而本領(lǐng)域現(xiàn)有技術(shù)的算法始終將虛節(jié)點(diǎn)保持于隊(duì)列中。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,僅當(dāng)有必要防止隊(duì)列變空時(shí)才使虛節(jié)點(diǎn)入列到隊(duì)列中。也就是說,僅在出列操作過程中并且僅當(dāng)在該出列操作過程中隊(duì)列包含單個(gè)用戶節(jié)點(diǎn)時(shí)才使虛節(jié)點(diǎn)入列。如果至少兩個(gè)用戶節(jié)點(diǎn)入列,則虛節(jié)點(diǎn)無需入列。相對于總是將虛節(jié)點(diǎn)保持于隊(duì)列中的常規(guī)機(jī)制如Forin等人的專利中描述的機(jī)制而言,這減少了開銷。為了展現(xiàn)這一優(yōu)點(diǎn)而構(gòu)造了測試,其中使用根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法(在下文的"詳述"部分中將更具體地描述)以及Forin等人的專利中描述的方法針對十秒間隔由十六個(gè)線程反復(fù)地使十六個(gè)用戶節(jié)點(diǎn)入列和出列。測試結(jié)果在下表l中示出。表1<table>tableseeoriginaldocumentpage13</column></row><table>如表1中所示,F(xiàn)orin等人的專利中描述的算法每十七個(gè)隊(duì)列使虛節(jié)點(diǎn)入列一次。作為對比,根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法僅在測試運(yùn)行結(jié)束時(shí)使虛節(jié)點(diǎn)重新入列一次。此外,根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法與Forin等人的專利中描述的算法相比能夠在十秒間隔中使多出50%以上的用戶節(jié)點(diǎn)入列。此外,F(xiàn)orin等人的專利中描述的算法由于之前討論過的出列時(shí)間窗缺陷而在測試運(yùn)行結(jié)束時(shí)在隊(duì)列中不利地留下十三個(gè)用戶節(jié)點(diǎn)。總的來說,測試已經(jīng)表明,當(dāng)生產(chǎn)者線程(入列)和消費(fèi)者線程(出列)以近似相同的速率運(yùn)行時(shí),根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法很少使虛節(jié)點(diǎn)入列。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,用戶節(jié)點(diǎn)直接入列到隊(duì)列中并且能夠按照任何線程的要求立即出列。根據(jù)本發(fā)明優(yōu)選實(shí)施例的算法事實(shí)上能夠用于包括低級內(nèi)核中斷句柄的所有編程環(huán)境中。因而,本發(fā)明的優(yōu)選實(shí)施例與需要額外鏈接節(jié)點(diǎn)存儲器管理的常規(guī)機(jī)制如Michael公開內(nèi)容中的機(jī)制形成對比,其中該額外鏈接節(jié)點(diǎn)存儲器管理限制了這些常規(guī)機(jī)制的使用。因而,這樣的常規(guī)機(jī)制不能很好地適合于例如具有存儲器分配限制的中斷句柄。2.0詳述現(xiàn)在將在特定計(jì)算機(jī)系統(tǒng)100即IBMeServeriSeries或者Systemi計(jì)算機(jī)系統(tǒng)的背景下參照圖1來描述本發(fā)明優(yōu)選實(shí)施例的計(jì)算機(jī)系統(tǒng)實(shí)施。然而,本領(lǐng)域技術(shù)人員將認(rèn)識到,本發(fā)明的FIFO隊(duì)列、方法、裝置和計(jì)算機(jī)程序產(chǎn)品同樣適用于任何計(jì)算機(jī)系統(tǒng),無論該計(jì)算機(jī)系統(tǒng)是復(fù)雜的多用戶計(jì)算裝置、單用戶工作站、PC還是嵌入式控制系統(tǒng)。如圖1中所示,計(jì)算機(jī)系統(tǒng)100包括一個(gè)或者多個(gè)處理器IOIA、IOIB、101C和101D、主存儲器102、海量存儲接口104、顯示器接口106、網(wǎng)絡(luò)接口108和1/0設(shè)備接口109。這些系統(tǒng)組件通過使用系統(tǒng)總線110來互連。圖1旨在于在較高級別上描繪計(jì)算機(jī)系統(tǒng)100的代表性的主要組件,應(yīng)理解到各個(gè)組件可以具有比圖1中所示更大的復(fù)雜度而且這樣的組件的數(shù)目、類型和配置可以變化。例如,計(jì)算機(jī)系統(tǒng)100可以包含與所示數(shù)目不同的處理器。海量存儲接口104用來將海量存儲設(shè)備(比如直接存取存儲設(shè)備112)連接到計(jì)算機(jī)系統(tǒng)100。直接存取存儲設(shè)備112的一個(gè)具體類型是可以存儲數(shù)據(jù)到CDROM114和從CDROM114讀取數(shù)據(jù)的可讀可寫CDROM驅(qū)動器。根據(jù)優(yōu)選實(shí)施例的主存儲器102包含數(shù)據(jù)116、操作系統(tǒng)118和入列/出列機(jī)制120。盡管入列/出列機(jī)制120在圖1中表示為與操作系統(tǒng)118相分離和分立,但是優(yōu)選實(shí)施例明確地延及在操作系統(tǒng)118和/或內(nèi)核內(nèi)實(shí)施的入列/出列機(jī)制120。正如本領(lǐng)域中乂>知的,內(nèi)核可以集成到操作系統(tǒng)118中并且將內(nèi)核級服務(wù)提供給操作系統(tǒng)118和其它程序。例如,入列/出列機(jī)制120可以實(shí)施于內(nèi)核中包含的中斷句柄和/或系統(tǒng)任務(wù)調(diào)度器中。此外,在優(yōu)選實(shí)施例的范圍內(nèi),入列/出列機(jī)制120能夠獨(dú)自或者一起實(shí)施于應(yīng)用軟件、實(shí)用程序或者其它類型的軟件中。例如,本發(fā)明適用于范圍廣泛的應(yīng)用,如數(shù)據(jù)庫、聯(lián)網(wǎng)、任務(wù)調(diào)度和存儲管理。計(jì)算機(jī)系統(tǒng)100利用公知的虛擬尋址機(jī)制,這些機(jī)制使得計(jì)算機(jī)系統(tǒng)100的程序可以表現(xiàn)得好像它們是訪問大型單個(gè)存儲實(shí)體而不是訪問多個(gè)小型存儲實(shí)體如主存儲器102和DASD設(shè)備112—樣。因此,盡管數(shù)據(jù)116、操作系統(tǒng)118和入列/出列機(jī)制120被表示為駐留于主存儲器102中,但是本領(lǐng)域技術(shù)人員將認(rèn)識到這些項(xiàng)目并非必然同時(shí)全都完全地包含于主存儲器102中。也應(yīng)當(dāng)注意,術(shù)語"存儲器"在這里用來一般地指代計(jì)算機(jī)系統(tǒng)100的整個(gè)虛擬存儲器。數(shù)據(jù)116代表了用作對計(jì)算機(jī)系統(tǒng)100中任何程序的輸入或者來自該程序的輸出的任何數(shù)據(jù)。操作系統(tǒng)118是業(yè)內(nèi)稱為OS/400或者IBMi5/OS的多任務(wù)操作系統(tǒng);然而本領(lǐng)域技術(shù)人員認(rèn)識到本發(fā)明的精神和范圍不限于任何一個(gè)操作系統(tǒng)。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,入列/出列機(jī)制120提供了正如下文將具體討論的用于實(shí)施并發(fā)非阻塞無鎖FIFO隊(duì)列的功能。另外,根據(jù)本發(fā)明的優(yōu)選實(shí)施例,入列/出列機(jī)制120包括圖5中所示Queue類和Node結(jié)構(gòu)的數(shù)據(jù)布局、用于圖6中所示入列函數(shù)的代碼、用于圖7中所示enqueueStep2函數(shù)的代碼、用于圖8中所示出列函數(shù)的代碼以及用于圖9中所示enqueueDummy函數(shù)的代碼。入列/出列機(jī)制120可以預(yù)先加以編程、手工加以編程、乂人記錄介質(zhì)(例如CDROM114)加以傳送或者通過因特網(wǎng)(例如通過網(wǎng)絡(luò)126)來下載。處理器101A、101B、101C和101D(在這里也統(tǒng)稱為"處理器1or,)可以由一個(gè)或者多個(gè)微處理器和/或集成電路構(gòu)成。處理器ioi執(zhí)行主存儲器102中存儲的程序指令。主存儲器102存儲可以由處理器101訪問的程序和數(shù)據(jù)。當(dāng)計(jì)算機(jī)系統(tǒng)100啟動時(shí),處理器101初始地執(zhí)行構(gòu)成操作系統(tǒng)118的程序指令。操作系統(tǒng)118是管理計(jì)算機(jī)系統(tǒng)100的資源的復(fù)雜系統(tǒng)。這些資源中的一些資源是處理器101、主存儲器102、海量存儲接口104、顯示器接口106、網(wǎng)絡(luò)接口108、1/0設(shè)備接口109和系統(tǒng)總線110。雖然計(jì)算機(jī)系統(tǒng)100表示為包含四個(gè)處理器和單個(gè)系統(tǒng)總線,但是本領(lǐng)域技術(shù)人員將認(rèn)識到可以使用具有不同數(shù)目的處理器和/或多個(gè)總線的計(jì)算機(jī)系統(tǒng)來實(shí)施本發(fā)明。此外,在優(yōu)選實(shí)施例中使用的接口均包括分離的完全編程微處理器,這些微處理器用來從處理器101卸載計(jì)算密集的處理。然而,本領(lǐng)域技術(shù)人員將認(rèn)識到本發(fā)明同樣適用于如下計(jì)算機(jī)系統(tǒng),這些計(jì)算機(jī)系統(tǒng)簡單地使用I/O適配器來執(zhí)行相似的功能。顯示器接口106用來將一個(gè)或者多個(gè)顯示器122直接連接到計(jì)算機(jī)系統(tǒng)100。這些顯示器122可以是非智能終端(即啞終端)或者完全可編程工作站,這些顯示器122被用來使得系統(tǒng)管理員和用戶(在這里也稱為"操作者")可以與計(jì)算機(jī)系統(tǒng)100通信。然而,注意到盡管提供顯示器接口106以支持與一個(gè)或者多個(gè)顯示器122的通信,但是計(jì)算機(jī)系統(tǒng)IOO并非必然地需要顯示器122,因?yàn)樗兴璧呐c用戶和處理的交互可以經(jīng)由網(wǎng)絡(luò)接口108進(jìn)行。網(wǎng)絡(luò)接口108用來i爭經(jīng)網(wǎng)絡(luò)126將其它計(jì)算^L系統(tǒng)和/或工作站124連接到計(jì)算機(jī)系統(tǒng)100。無論計(jì)算機(jī)系統(tǒng)IOO可以如何連接到其它計(jì)算機(jī)系統(tǒng),不管使用如今的模擬和/或數(shù)字技術(shù)還是經(jīng)由將來的某一聯(lián)網(wǎng)機(jī)制來實(shí)現(xiàn)網(wǎng)絡(luò)連接126,本發(fā)明都同樣適用。此外,很多不同網(wǎng)絡(luò)協(xié)議能夠用來實(shí)施網(wǎng)絡(luò)。這些協(xié)議是使得計(jì)算機(jī)可以跨經(jīng)網(wǎng)絡(luò)126進(jìn)行通信的專用計(jì)算機(jī)程序。TCP/IP(傳輸控制協(xié)議/網(wǎng)際協(xié)議)是適當(dāng)網(wǎng)絡(luò)協(xié)議的例子。I/O設(shè)備接口109提供通向各種輸入/輸出設(shè)備中任何輸入/輸出設(shè)備的接口。此時(shí),重要的是注意到盡管已經(jīng)以及將會在完全功能計(jì)算機(jī)系統(tǒng)的背景下描述本發(fā)明的這一實(shí)施例,但是本領(lǐng)域技術(shù)人員將認(rèn)識到本發(fā)明能夠作為各種形式的程序產(chǎn)品來分發(fā),并且無論用來實(shí)際地實(shí)現(xiàn)該分發(fā)的信號承載介質(zhì)的特定類型如何,本發(fā)明都同樣地適用。適當(dāng)信號承載介質(zhì)的例子包括可記錄型介質(zhì)如軟盤和CDROM(例如圖1的CDROM114)以及傳輸型介質(zhì)如數(shù)字和才莫擬通信鏈路(例如圖1中的網(wǎng)絡(luò)126)。圖2是根據(jù)本發(fā)明優(yōu)選實(shí)施例的FIFO隊(duì)列200的初始狀態(tài)的框圖。一般而言,F(xiàn)IFO隊(duì)列200包括指定一系列節(jié)點(diǎn)的存儲列表,這些節(jié)點(diǎn)是比如圖1中所示主存儲器102這樣的包含數(shù)據(jù)的存儲器中的位置。虛節(jié)點(diǎn)不可用于外部線程。另一方面,外部進(jìn)程或者應(yīng)用線程可以使用戶節(jié)點(diǎn)入列和出列。在圖2中所示FIFO隊(duì)列的初始狀態(tài)下(即恰在構(gòu)造它之后),包括FIFO隊(duì)列200的存儲列表被指定如下具有"next"指針204的虛節(jié)點(diǎn)202;指向虛節(jié)點(diǎn)202的頭指針206;指向虛節(jié)點(diǎn)202的尾指針208;以及指向虛節(jié)點(diǎn)202的虛指針210。因此,隊(duì)列的頭指針、尾指針和虛指針全部初始地指向虛節(jié)點(diǎn)202。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,僅使多個(gè)虛節(jié)點(diǎn)入列以防止FIFO隊(duì)列200變得在邏輯上為空。當(dāng)僅有一個(gè)虛節(jié)點(diǎn)入列時(shí)FIFO隊(duì)列200才"在邏輯上為空"。由于這時(shí)在虛節(jié)點(diǎn)202之后沒有下一節(jié)點(diǎn),所以虛節(jié)點(diǎn)的"next"指針204優(yōu)選地設(shè)置為NULL。圖3是圖示了根據(jù)本發(fā)明優(yōu)選實(shí)施例的入列操作的框圖,其中用戶節(jié)點(diǎn)302入列到圖2中所示FIFO隊(duì)列200的初始狀態(tài),即在邏輯上為空的隊(duì)列。用戶節(jié)點(diǎn)302具有"next"指針304。由于這時(shí)在用戶節(jié)點(diǎn)302之后沒有下一節(jié)點(diǎn),所以用戶節(jié)點(diǎn)的"next"指針304優(yōu)選地設(shè)置為NULL。虛節(jié)點(diǎn)202保留于FIFO200中直至自然地出列,即使FIFO隊(duì)列200并非在邏輯上為空。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,圖3中所示入列操作在兩個(gè)步驟中發(fā)生。首先,入列操作將新節(jié)點(diǎn)即用戶節(jié)點(diǎn)302入列到FIFO隊(duì)列200的末尾(步驟351)。這通過將虛節(jié)點(diǎn)的"next"指針204設(shè)置為指向用戶節(jié)點(diǎn)302來實(shí)現(xiàn)。然后,將隊(duì)列的尾指針208更新為指向新節(jié)點(diǎn)即用戶節(jié)點(diǎn)302(步驟352)。圖4A、圖4B和圖4C是共同圖示了根據(jù)本發(fā)明優(yōu)選實(shí)施例的出列操作的框圖。具體而言,圖4A-圖4C一起圖示了虛節(jié)點(diǎn)如何出列,然后在最后一個(gè)用戶節(jié)點(diǎn)出列時(shí)如何重新入列。在圖4A中,虛節(jié)點(diǎn)202從圖3中所示狀態(tài)下的FIFO隊(duì)列200中出列。在圖4B中,虛節(jié)點(diǎn)重新入列到圖4A中所示狀態(tài)下的FIFO隊(duì)列200中。在圖4C中,用戶節(jié)點(diǎn)302乂人圖4B中所示狀態(tài)下的FIFO隊(duì)列200中出列。應(yīng)當(dāng)理解,根據(jù)本發(fā)明的優(yōu)選實(shí)施例,圖4A-圖4C中所示場景是一種異常情況。這是因?yàn)樵诜€(wěn)定狀態(tài)過程中,假設(shè)隊(duì)列中有至少兩個(gè)用戶節(jié)點(diǎn),虛節(jié)點(diǎn)很少出列。雖然圖4A-圖4C中所示場景是一種異常情況,但是這一場景對于從如何根據(jù)本發(fā)明優(yōu)選實(shí)施例來使用虛節(jié)點(diǎn)的角度進(jìn)行理解是重要的。在圖4A中,虛節(jié)點(diǎn)202從圖3中所示狀態(tài)下的FIFO隊(duì)列200中出列。虛節(jié)點(diǎn)202之所以出列是因?yàn)樗荈IFO隊(duì)列200中的第一個(gè)節(jié)點(diǎn)。虛節(jié)點(diǎn)202在這時(shí)被放在一邊。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,虛節(jié)點(diǎn)202的出列被實(shí)現(xiàn)如下。隊(duì)列的頭指針206被設(shè)置為指向用戶節(jié)點(diǎn)302(步驟451)。此外,虛節(jié)點(diǎn)的"next"指針204被設(shè)置為NULL(步驟452)。在圖4B中,虛節(jié)點(diǎn)重新入列到圖4A中所示狀態(tài)下的FIFO隊(duì)列200中。重新入列的虛節(jié)點(diǎn)在圖4B中表示為虛節(jié)點(diǎn)402。虛節(jié)點(diǎn)402優(yōu)選地設(shè)置為虛節(jié)點(diǎn)202或者可以是另一虛節(jié)點(diǎn)。在任何情況下,在最后一個(gè)用戶節(jié)點(diǎn)能夠出列之前虛節(jié)點(diǎn)必須重新入列。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,虛節(jié)點(diǎn)402的重新入列被實(shí)現(xiàn)如下。當(dāng)前尾節(jié)點(diǎn)的"next"指針304被設(shè)置為指向虛節(jié)點(diǎn)402(步驟453)。以這一方式,虛節(jié)點(diǎn)402被鏈接到FIFO隊(duì)列200的末尾。然后,隊(duì)列的尾指針208被設(shè)置為指向虛節(jié)點(diǎn)402(步驟454)。此外,由于這時(shí)在虛節(jié)點(diǎn)202之后沒有下一節(jié)點(diǎn),所以虛節(jié)點(diǎn)的"next"指針404被設(shè)置為NULL。在圖4C中,用戶節(jié)點(diǎn)302從圖4B中所示狀態(tài)下的FIFO隊(duì)列200中出列。使用戶節(jié)點(diǎn)302出列,在FIFO隊(duì)列200中僅留下虛節(jié)點(diǎn)402j艮據(jù)本發(fā)明的優(yōu)選實(shí)施例,用戶節(jié)點(diǎn)302的出列;陂實(shí)現(xiàn)如下。隊(duì)列的頭指針206被設(shè)置為指向虛節(jié)點(diǎn)402(步驟455)。另外,用戶節(jié)點(diǎn)的"next"指針304被設(shè)置為NULL(步驟456)。根據(jù)本發(fā)明的優(yōu)選實(shí)施例,隊(duì)列必須原子性地更新三個(gè)無關(guān)指針隊(duì)列的頭指針;隊(duì)列的尾指針;以及節(jié)點(diǎn)的"next"指針。不能同時(shí)原子性地更新所有三個(gè)指針,使得這成為難以解決的問題。加載鏈接/條件存儲同步原語將原子性地更新一個(gè)指針并且使得可以測試(加載)在加載鏈接與條件存儲之間的無關(guān)共享存儲器。比較和交換(CAS)同步原語能夠用作備選的原語;然而,將需要解決CAS同步原語中固有的ABA問題,并且其實(shí)施將明顯地不那么高效。圖5是用來圖示根據(jù)本發(fā)明優(yōu)選實(shí)施例的Node結(jié)構(gòu)和Queue類的數(shù)據(jù)布局的偽隨機(jī)代碼的示圖。Node結(jié)構(gòu)在行501處示出。Queue類在行502處示出并且聲明了如下函數(shù)enqueue;enqueueStep2;dequeue;以及enqueueDummy。在行503處示出的enqueue函數(shù)是用以使新節(jié)點(diǎn)入列的公共接口。在行505處的enqueueStep2函數(shù)是執(zhí)行入列才喿作的后一半操作的專用函數(shù)。在行504處的出列函數(shù)是用以使節(jié)點(diǎn)出列的公共接口。在行506處的enqueueDummy函數(shù)在需要的情況下使虛節(jié)點(diǎn)入列。節(jié)點(diǎn)可以是用戶節(jié)點(diǎn)或者虛節(jié)點(diǎn)。用戶節(jié)點(diǎn)由用戶分配并且包含用戶特有數(shù)據(jù)。每隊(duì)列被分配一個(gè)虛節(jié)點(diǎn)而該虛節(jié)點(diǎn)對于用戶而言不可見。本領(lǐng)域技術(shù)人員將認(rèn)識到圖5中所示Queue類和Node結(jié)構(gòu)的數(shù)據(jù)布局是示例性的。其它實(shí)施也在本發(fā)明的精神和范圍內(nèi)。例如,Queue類能夠?qū)嵤槟0孱?,該模板類指定Node作為模板參數(shù)用以使用戶的Node結(jié)構(gòu)的布局廣義化。為求簡潔和清楚,圖示了非模板類。入列操作是兩步驟的過程1.將新節(jié)點(diǎn)鏈接到隊(duì)列的末尾。2.將隊(duì)列的尾指針更新為指向新節(jié)點(diǎn)。第一步驟,即將新節(jié)點(diǎn)鏈接到隊(duì)列的末尾,對應(yīng)于圖5的Queue類中行503處表示的入列功能并且在下文中將參照圖6具體加以討論。第二步驟,即將隊(duì)列的尾指針更新為指向新節(jié)點(diǎn),對應(yīng)于圖5的Queue類中行505處聲明的enqueueStep2函數(shù)并且在下文中將參照圖7具體加以討論。一般而言,入列操作總是假設(shè)至少一個(gè)節(jié)點(diǎn)總是入列到隊(duì)列中。應(yīng)當(dāng)理解,圖6-圖9中圖示的示例性偽代碼用于舉例說明而不用以限制本發(fā)明。本領(lǐng)域技術(shù)人員將認(rèn)識到其它實(shí)施也在本發(fā)明的精神和范圍內(nèi)。例如,各種步驟按它們的優(yōu)選順序在圖6-圖9中闡明。然而,必須理解,各種步驟可以在與圖中所示不同的時(shí)間發(fā)生或者可以同時(shí)發(fā)生。另外,本領(lǐng)域技術(shù)人員將認(rèn)識到可以省略這些步驟中的一個(gè)或者多個(gè)步驟。圖6是用來圖示圖5的Queue類中行503處聲明的入列函數(shù)的示例性偽代碼的示圖。在行601處,入列函數(shù)始于如下代碼,該代碼繼續(xù)循環(huán)直至新節(jié)點(diǎn)成功地被鏈接到隊(duì)列的末尾。在行602處得到隊(duì)列尾指針的快照(snapshot)。隊(duì)列的尾指針總是被假設(shè)為非NULL,因?yàn)榭偸怯兄辽僖粋€(gè)節(jié)點(diǎn)入列。在行603處,得到尾節(jié)點(diǎn)"next"指針的快照而設(shè)置預(yù)留以檢測任何到尾節(jié)點(diǎn)"next"指針的存儲。在行604處,對于弱一致性處理器而言需要存儲排序防護(hù)以保證尾節(jié)點(diǎn)的"next"指針在它被測試之前是當(dāng)前指針(在行605處)。在行605處,如果尾部尚未改變,則意味著仍然對當(dāng)前尾節(jié)點(diǎn)進(jìn)行操作而隊(duì)列的尾指針與尾節(jié)點(diǎn)的"next"指針是一致的。如果尾部已經(jīng)改變,則入列函數(shù)在行601處重新開始。在行605.1處,如果當(dāng)前尾節(jié)點(diǎn)的"next"指針為非NULL,則這意味著入列操作部分地完成而必須更新尾部,因而調(diào)用enqueueStep2(下文將參照圖7加以討論)以幫助完成部分入列。先前的入列必須在下一入列能夠開始之前完成,因而入列函數(shù)在行601處重新開始。在行605.2處,入列函數(shù)現(xiàn)在嘗試有條件地將新節(jié)點(diǎn)鏈接到隊(duì)列的末尾。如果另一線程當(dāng)前正在使節(jié)點(diǎn)入列則條件存儲可能失敗。在行606處,入列函數(shù)的最后步驟調(diào)用enqueueStep2(下文將參照圖7加以討論)以將隊(duì)列的尾指針更新為指向新節(jié)點(diǎn)。圖7是用來圖示圖5的Queue類中行505處聲明的enqueueStep2函數(shù)的示例性偽代碼的示圖。enqueueStep2函數(shù)既可以由入列函數(shù)調(diào)用又可以由出列函數(shù)調(diào)用,以幫助完成部分入列。在行701處,enqueueStep2函數(shù)始于如下代碼,該代碼繼續(xù)循環(huán)直至尾部更新。這是能夠由多個(gè)線程并發(fā)執(zhí)行的協(xié)作工作。因此,有可能另一線程可以在這一線程能夠更新尾部并且沒有必要進(jìn)行更新之前更新尾部。在行702處,得到隊(duì)列尾指針的快照而設(shè)置預(yù)留以檢測任何到隊(duì)列尾指針的存儲。在行703處,對于弱一致性處理器而言需要存儲排序防護(hù)以保證尾節(jié)點(diǎn)的"next"指針是當(dāng)前指針。在行704處,得到尾節(jié)點(diǎn)的"next"指針的快照。在行705處,如果尾節(jié)點(diǎn)的"next"指針為NULL,則由于尾部已經(jīng)被另一線程更新所以退出循環(huán)。在行706處,enqueueStep2函數(shù)嘗試有條件地將隊(duì)列的尾指針擺動到下一節(jié)點(diǎn)。如果另一線程當(dāng)前正在執(zhí)行enqueueStep2則條件存儲可能失敗。出列操作比入列操作略微復(fù)雜一些。出列考慮事項(xiàng)包括如果虛節(jié)點(diǎn)出列,則將它放在一邊而嘗試使下一節(jié)點(diǎn)出列。如果僅單個(gè)用戶節(jié)點(diǎn)入列,則在使該用戶節(jié)點(diǎn)出列之前使虛節(jié)點(diǎn)入列。隊(duì)列一定不能為空。如果頭節(jié)點(diǎn)部分地出列,則幫助完成入列。當(dāng)前頭節(jié)點(diǎn)直至完全地入列才能夠出列。如果隊(duì)列在邏輯上為空,則返回NULL。如前所述,僅當(dāng)虛節(jié)點(diǎn)入列時(shí)隊(duì)列才在邏輯上為空。圖8是用來圖示圖5的Queue類中行504處聲明的出列函數(shù)的示例性偽代碼的示圖。在行801處,出列函數(shù)始于如下代碼,該代碼繼續(xù)循環(huán)直至用戶節(jié)點(diǎn)成功地出列或者檢測到在邏輯上為空的隊(duì)列。在行802處,得到隊(duì)列頭指針的快照而設(shè)置預(yù)留以檢測任何到隊(duì)列頭指針的存儲。在行803處,對于弱一致性處理器而言需要存儲排序防護(hù)以保證頭節(jié)點(diǎn)的"next"指針和隊(duì)列的尾指針是當(dāng)前指針。在行804處,得到頭節(jié)點(diǎn)的"next"指針的快照。在行805處,如果隊(duì)列的頭指針和尾指針相等,則隊(duì)列的狀態(tài)將不允許使節(jié)點(diǎn)出列。執(zhí)行這些動作之一以改變隊(duì)列狀態(tài)從而允許使節(jié)點(diǎn)出列。這三個(gè)動作分別在行805.1、805.1和805.3處示出。在行805.1處,如果隊(duì)列中的唯一節(jié)點(diǎn)是虛節(jié)點(diǎn),這隊(duì)列在邏輯上為空。執(zhí)行條件存儲以檢驗(yàn)隊(duì)列的頭指針是否尚未改變。如果頭部尚未改變,則出列函數(shù)返回NULL以指示隊(duì)列為空。如果頭部已經(jīng)改變,則出列函數(shù)在行801處重新開始。在行805.2處,如果隊(duì)列中的唯一節(jié)點(diǎn)是用戶節(jié)點(diǎn),則調(diào)用enqueueDummy函數(shù)(下文將參照圖9加以討論)以使虛節(jié)點(diǎn)入列。在使虛節(jié)點(diǎn)入列之后,能夠使用戶節(jié)點(diǎn)出列。因而,一旦虛節(jié)點(diǎn)入列,出列函數(shù)就在行801處重新開始。在行805.3處,如果第二節(jié)點(diǎn)部分地入列,則調(diào)用enqueueStep2函數(shù)(上文已參照圖7加以討論)以通過更新隊(duì)列的尾指針來幫助完成入列。一旦enqueueStep2函數(shù)完成,出列函數(shù)就在行801處重新開始。在行806處,出列函數(shù)嘗試有條件地使頭節(jié)點(diǎn)出列。如果另一線程并發(fā)地正在使節(jié)點(diǎn)出列則條件存儲可能失敗。如果條件存儲成功則執(zhí)行如下步驟。在行806.1處,出列節(jié)點(diǎn)的"next"指針被設(shè)置為NULL。這使得出列節(jié)點(diǎn)準(zhǔn)備再次入列。在行806.2處,如果出列節(jié)點(diǎn)是用戶節(jié)點(diǎn),則將用戶節(jié)點(diǎn)返回給調(diào)用者。另一方面,在行806.3處,如果出列節(jié)點(diǎn)為虛節(jié)點(diǎn),則該虛節(jié)點(diǎn)被放在一邊而出列函數(shù)在行801處重新開始以使用戶節(jié)點(diǎn)出列。圖9是用來圖示圖5的Queue類中行506處聲明的enqueueDummy函凄史的示例性偽石馬的示圖。enqueueDummy函凄丈4又當(dāng)隊(duì)列包含單個(gè)用戶節(jié)點(diǎn)時(shí)才使虛節(jié)點(diǎn)入列。在行901處,enqueueDummy函數(shù)始于如下代碼,該代碼繼續(xù)循環(huán)直至虛節(jié)點(diǎn)成功地入列或者虛節(jié)點(diǎn)不再需要入列。在行902處,得到隊(duì)列尾指針的快照。在行903處,得到尾節(jié)點(diǎn)"next"指針的快照而設(shè)置預(yù)留以檢測任何到尾節(jié)點(diǎn)"next"指針的存儲。在行904處,對于弱一致性處理器而言需要存儲排序防護(hù)以保證隊(duì)列的頭指針和尾指針是當(dāng)前指針。在行905處,enqueueDummy函數(shù)檢驗(yàn)是否仍然需要添加虛節(jié)點(diǎn)。首先,檢驗(yàn)尾部是否尚未改變(即如果尾部改變,則意味著另一節(jié)點(diǎn)正在入列,因而在該情況下沒有必要使虛節(jié)點(diǎn)入列)。其次,檢驗(yàn)隊(duì)列的頭指針和尾指針是否相等(即是否僅一個(gè)節(jié)點(diǎn)入列)。然后,檢驗(yàn)尾節(jié)點(diǎn)的"next"指針是否為NULL(即如果尾節(jié)點(diǎn)的"next"指針為非NULL,則這意味著部分入列正在進(jìn)行)。第四,檢驗(yàn)虛節(jié)點(diǎn)是否尚未入列。在行905.1處,enqueueDummy函數(shù)現(xiàn)在嘗試有條件地使虛節(jié)點(diǎn)入列。如果另一線程并發(fā)地正在使節(jié)點(diǎn)入列則條件存儲可能失敗。^口果虛節(jié)力、成功;也入歹'J,貝'JenqueueDummy函凄丈完成。否則enqueueDummy函凄t在4亍901處重#斤開士臺。在行906處,如果虛節(jié)點(diǎn)不再需要入列,則enqueueDummy函數(shù)完成。也就是說,在行905處檢驗(yàn)的四個(gè)條件之一為"假"(false)。本領(lǐng)域技術(shù)人員將認(rèn)識到在本發(fā)明的范圍內(nèi)可以進(jìn)行很多變更。例如,盡管入列/出列機(jī)制被表示為與圖1中的操作系統(tǒng)相分離和分立,但是本發(fā)明延及在操作系統(tǒng)和/或內(nèi)核內(nèi)的實(shí)施。此外,本發(fā)明能夠用應(yīng)用軟件、實(shí)用程序或者其它類型的軟件獨(dú)自或者一起加以實(shí)施。例如,本發(fā)明適用于范圍廣泛的應(yīng)用,如^:據(jù)庫、聯(lián)網(wǎng)、任務(wù)調(diào)度和存儲管理。因此,盡管已經(jīng)參照本發(fā)明的優(yōu)選實(shí)施例具體地示出和描述了本發(fā)明,但是本領(lǐng)域技術(shù)人員將理解到,在不脫離本發(fā)明的精神和范圍的情況下,可以在其中做出形式和細(xì)節(jié)上的這些以及其它改變。權(quán)利要求1.一種無鎖并發(fā)FIFO隊(duì)列,包括至少一個(gè)用戶節(jié)點(diǎn),各用戶節(jié)點(diǎn)具有指向下一節(jié)點(diǎn)的“next”指針;虛節(jié)點(diǎn),具有指向下一節(jié)點(diǎn)的“next”指針,其中在出列操作過程中并且僅當(dāng)在所述出列操作過程中所述無鎖并發(fā)FIFO隊(duì)列包含所述用戶節(jié)點(diǎn)中的單個(gè)節(jié)點(diǎn)時(shí),所述虛節(jié)點(diǎn)才入列;標(biāo)識頭節(jié)點(diǎn)的頭指針;標(biāo)識尾節(jié)點(diǎn)的尾指針;標(biāo)識所述虛節(jié)點(diǎn)的虛指針。2.如權(quán)利要求1所述的無鎖并發(fā)FIFO隊(duì)列,其中所述虛節(jié)點(diǎn)不包含在所述無鎖并發(fā)FIFO隊(duì)列中,并且其中在所述出列操作過程中所述無鎖并發(fā)FIFO隊(duì)列包含兩個(gè)或者更多用戶節(jié)點(diǎn),使得所述虛節(jié)點(diǎn)在所述出列操作過程中不入列。3.—種實(shí)施隊(duì)列的方法,包括以下步驟(a)使用戶節(jié)點(diǎn)入列到隊(duì)列的末尾,其中在所述入列步驟(a)之前,所述隊(duì)列至少包括具有指向下一節(jié)點(diǎn)的"next"指針的虛節(jié)點(diǎn),并且其中所述用戶節(jié)點(diǎn)具有指向下一節(jié)點(diǎn)的"next"指針;(b)在所述入列步驟(a)之后,使所述虛節(jié)點(diǎn)從所述隊(duì)列中出列;(c)在所述出列步驟(b)之后,有條件地使頭節(jié)點(diǎn)從所述隊(duì)列中出列;(d)在所述有條件的出列步驟(c)過程中,僅當(dāng)所述隊(duì)列包含僅一個(gè)用戶節(jié)點(diǎn)時(shí)才使另一虛節(jié)點(diǎn)入列到所述隊(duì)列的末尾。4.如權(quán)利要求3所述的方法,其中所述入列步驟(a)包括以下步驟通過將尾節(jié)點(diǎn)的"next"指針設(shè)置為指向所述用戶節(jié)點(diǎn)而將所述用戶節(jié)點(diǎn)鏈接到所述隊(duì)列的末尾;將所述隊(duì)列的尾指針更新為指向所述用戶節(jié)點(diǎn)。5.如權(quán)利要求4所述的方法,其中所述更新步驟不是在所述入列步驟(a)過程中完成而是在后續(xù)入列操作或者后續(xù)出列操作過程中完成。6.如權(quán)利要求3所述的方法,其中如果所述有條件的出列步驟(c)成功地使得節(jié)點(diǎn)出列,則所述方法還包括以下步驟將步驟(c)中出列的節(jié)點(diǎn)的"next"指針設(shè)置為NULL;如果步驟(c)中出列的節(jié)點(diǎn)為用戶節(jié)點(diǎn),則返回所述出列的用戶節(jié)點(diǎn);如果步驟(c)中出列的節(jié)點(diǎn)為虛節(jié)點(diǎn),則重新開始所述有條件的出列步驟(c)。7.如權(quán)利要求3所述的方法,其中所述入列步驟(a)、所述出列步驟(b)、所述有條件的出列步驟(c)和所述入列步驟(d)均包括使用加載鏈接/條件存儲原語。8.如權(quán)利要求7所述的方法,其中所述入列步驟(a)、所述出列步驟(b)、所述有條件的出列步驟(c)和所述入列步驟(d)均包括使用存儲排序防護(hù)。9.一種用于實(shí)施隊(duì)列的裝置,包括至少一個(gè)處理器;耦合到所述至少一個(gè)處理器的存儲器;由在所述至少一個(gè)處理器上運(yùn)行的至少一個(gè)線程入列和出列的無鎖并發(fā)FIFO隊(duì)列,所述無鎖并發(fā)FIFO隊(duì)列包括至少一個(gè)用戶節(jié)點(diǎn),各用戶節(jié)點(diǎn)具有指向下一節(jié)點(diǎn)的"next"指針;虛節(jié)點(diǎn),具有指向下一節(jié)點(diǎn)的"next"指針,其中在出列操作過程中并且僅當(dāng)在所述出列操作過程中所述無鎖并發(fā)FIFO隊(duì)列包含所述用戶節(jié)點(diǎn)中的單個(gè)節(jié)點(diǎn)時(shí),所述虛節(jié)點(diǎn)才入列;標(biāo)識頭節(jié)點(diǎn)的頭指針;標(biāo)識尾節(jié)點(diǎn)的尾指針;標(biāo)識所述虛節(jié)點(diǎn)的虛指針。10.如權(quán)利要求9所述的裝置,其中所述虛節(jié)點(diǎn)不包含在所述無鎖并發(fā)FIFO隊(duì)列中,并且其中在所述出列操作過程中所述無鎖并發(fā)FIFO隊(duì)列包含兩個(gè)或者更多用戶節(jié)點(diǎn),使得所述虛節(jié)點(diǎn)在所述出列操作過程中不入列。11.一種用于在具有至少一個(gè)處理器的數(shù)字計(jì)算設(shè)備中實(shí)施隊(duì)列的計(jì)算機(jī)程序產(chǎn)品,包括在計(jì)算機(jī)可讀信號承載介質(zhì)上提供的多個(gè)可執(zhí)行指令,其中所述可執(zhí)行指令在由所述至少一個(gè)處理器執(zhí)行時(shí)使所述數(shù)字計(jì)算設(shè)備執(zhí)行以下步驟(a)使用戶節(jié)點(diǎn)入列到隊(duì)列的末尾,其中在所述入列步驟(a)之前,所述隊(duì)列至少包括具有指向下一節(jié)點(diǎn)的"next"指針的虛節(jié)點(diǎn),并且其中所述用戶節(jié)點(diǎn)具有指向下一節(jié)點(diǎn)的"next"指針;(b)在所述入列步驟(a)之后,使所述虛節(jié)點(diǎn)從所述隊(duì)列中出列;(c)在所述出列步驟(b)之后,有條件地使頭節(jié)點(diǎn)從所述隊(duì)列中出列;(d)在所述有條件的出列步驟(c)過程中,僅當(dāng)所述隊(duì)列包含僅一個(gè)用戶節(jié)點(diǎn)時(shí)才使另一虛節(jié)點(diǎn)入列到所述隊(duì)列的末尾。全文摘要僅當(dāng)有必要防止隊(duì)列變空時(shí)才使虛節(jié)點(diǎn)入列到并發(fā)非阻塞無鎖FIFO隊(duì)列中。僅在出列操作過程中并且僅當(dāng)在該出列操作過程中隊(duì)列包含單個(gè)用戶節(jié)點(diǎn)時(shí),虛節(jié)點(diǎn)才入列。這相對于總是將虛節(jié)點(diǎn)保持于隊(duì)列中的常規(guī)機(jī)制而言減少了開銷。用戶節(jié)點(diǎn)直接入列到隊(duì)列中并且能夠按照任何線程的要求立即出列。優(yōu)選地,入列和出列操作包括使用加載鏈接/條件存儲(LL/SC)同步原語。這解決了ABA問題而無需使用唯一編號如隊(duì)列特有編號,并且與包括使用比較和交換(CAS)同步原語以及通過使用唯一編號來解決ABA問題的常規(guī)機(jī)制形成對比。此外,優(yōu)選地插入存儲排序防護(hù)以使得算法可以在弱一致性處理器上運(yùn)行。文檔編號G06F5/10GK101183304SQ200710167568公開日2008年5月21日申請日期2007年10月26日優(yōu)先權(quán)日2006年11月13日發(fā)明者D·A·克里斯坦森申請人:國際商業(yè)機(jī)器公司