本發(fā)明涉及計(jì)算機(jī)多線程,原子操作,讀寫(xiě)鎖。具體來(lái)說(shuō),在多線程環(huán)境下,利用原子操作,實(shí)現(xiàn)高效的讀寫(xiě)鎖方法。
背景技術(shù):
在多線程環(huán)境下,有這樣一種場(chǎng)景(即一種單讀、單寫(xiě)的場(chǎng)景),對(duì)于一段共享數(shù)據(jù)隊(duì)列,只有一個(gè)用戶做寫(xiě)操作,同時(shí)也只有一個(gè)用戶做讀操作的情況下,如何提高線程讀寫(xiě)鎖效率;常用的方法是利用操作系統(tǒng)提供的線程鎖,如圖1所示,這種方式功能強(qiáng)大,適應(yīng)性高,但在此場(chǎng)景效率低,因?yàn)榫€程鎖采用的是阻塞的方式,另外,線程鎖調(diào)用本身也有開(kāi)銷(xiāo),如果大量的調(diào)用加鎖/解鎖的話,開(kāi)銷(xiāo)也比較大。
技術(shù)實(shí)現(xiàn)要素:
針對(duì)現(xiàn)有技術(shù)中存在的技術(shù)問(wèn)題,本發(fā)明的目的是提供一種高效讀寫(xiě)鎖的實(shí)現(xiàn)方法,本發(fā)明通過(guò)一種無(wú)需加鎖的方法,來(lái)實(shí)現(xiàn)2個(gè)線程(一個(gè)讀線程和一個(gè)寫(xiě)線程)對(duì)一個(gè)共享數(shù)據(jù)隊(duì)列的訪問(wèn)。
為了實(shí)現(xiàn)上述目的,本發(fā)明的解決方案是:
一種高效讀寫(xiě)鎖的實(shí)現(xiàn)方法,其步驟為:
1)程序的主線程初始化共享數(shù)據(jù)隊(duì)列,為該共享數(shù)據(jù)隊(duì)列設(shè)置一寫(xiě)線程和一讀線程,以及設(shè)置一整數(shù)變量M來(lái)保存該共享數(shù)據(jù)隊(duì)列最大長(zhǎng)度,設(shè)置一變量K保存當(dāng)前該共享數(shù)據(jù)隊(duì)列中的數(shù)據(jù)個(gè)數(shù);
2)當(dāng)該程序需要對(duì)該共享數(shù)據(jù)隊(duì)列進(jìn)行寫(xiě)操作時(shí),該主線程調(diào)用該共享數(shù)據(jù)隊(duì)列的寫(xiě)線程,該寫(xiě)線程做寫(xiě)操作前,先檢查K,如果K<M,則把要寫(xiě)的數(shù)據(jù)插入到該共享數(shù)據(jù)隊(duì)列的寫(xiě)端,并且增加K的計(jì)數(shù)值;
3)當(dāng)該程序需要對(duì)該共享數(shù)據(jù)隊(duì)列進(jìn)行讀操作時(shí),該主線程調(diào)用該共享數(shù)據(jù)隊(duì)列的讀線程,該讀線程做讀操作前,檢查K,如果K>0,則從該共享數(shù)據(jù)隊(duì)列的讀端讀取一個(gè)元素,并且減少K的計(jì)數(shù)值。
進(jìn)一步的,所述步驟2)中,如果K大于或等于M,即該共享數(shù)據(jù)隊(duì)列已滿,則丟棄當(dāng)前要寫(xiě)的數(shù)據(jù)。
進(jìn)一步的,所述步驟2)中,如果K大于或等于M,即該共享數(shù)據(jù)隊(duì)列已滿,則等待該共享數(shù)據(jù)隊(duì)列未滿時(shí),將當(dāng)前要寫(xiě)的數(shù)據(jù)插入到該共享數(shù)據(jù)隊(duì)列的寫(xiě)端,并且增加K的計(jì)數(shù)值。
進(jìn)一步的,所述步驟3)中,如果K=0,即該共享數(shù)據(jù)隊(duì)列為空,則采取等待或者輪詢的方式檢測(cè)該共享數(shù)據(jù)隊(duì)列中是否存在數(shù)據(jù),如果存在,則從該共享數(shù)據(jù)隊(duì)列的讀端讀取一個(gè)元素,并且減少K的計(jì)數(shù)值。
進(jìn)一步的,該共享數(shù)據(jù)隊(duì)列中的元素為寫(xiě)入數(shù)據(jù)的指針。
本發(fā)明的主要內(nèi)容包括:
a.程序的主線程初始化共享數(shù)據(jù)隊(duì)列,用一個(gè)整數(shù)變量M來(lái)保存該共享數(shù)據(jù)隊(duì)列最大長(zhǎng)度,K保存當(dāng)前該共享數(shù)據(jù)隊(duì)列中的數(shù)據(jù)個(gè)數(shù)。
b.當(dāng)程序需要對(duì)該共享數(shù)據(jù)隊(duì)列進(jìn)行寫(xiě)操作時(shí),主線程調(diào)用該共享數(shù)據(jù)隊(duì)列的寫(xiě)線程,該寫(xiě)線程做寫(xiě)操作前,先檢查K,如果K<M,運(yùn)行push操作,即把要寫(xiě)的數(shù)據(jù)插入到該共享數(shù)據(jù)隊(duì)列的寫(xiě)端,并且K++,如果K>=M,說(shuō)明該共享數(shù)據(jù)隊(duì)列已滿,那么可以采取丟棄或者等待的方式。
c.當(dāng)程序需要對(duì)該共享數(shù)據(jù)隊(duì)列進(jìn)行讀操作時(shí),主線程調(diào)用該共享數(shù)據(jù)隊(duì)列的讀線程,該讀線程做讀操作前,檢查K,如果K>0,執(zhí)行pop操作,即從該共享數(shù)據(jù)隊(duì)列的讀端讀取一個(gè)元素,K--,如果K=0,說(shuō)明該共享數(shù)據(jù)隊(duì)列為空,那么可以采取等待或者輪詢的方式。
與現(xiàn)有技術(shù)相比,本發(fā)明的優(yōu)點(diǎn)和積極效果為:
在本發(fā)明中,在單讀單寫(xiě)的情況下,通過(guò)整數(shù)加減操作,對(duì)共享數(shù)據(jù)隊(duì)列中的元素進(jìn)行訪問(wèn)。相對(duì)于采用線程鎖,本發(fā)明大大提高了讀寫(xiě)效率,消除了由于頻繁的調(diào)用線程鎖而產(chǎn)生的開(kāi)銷(xiāo)。
附圖說(shuō)明
圖1為傳統(tǒng)讀寫(xiě)鎖的流程圖;
圖2為本發(fā)明方法的流程圖。
具體實(shí)現(xiàn)方式
本發(fā)明流程如圖2所示,具體如下:
(1)程序啟動(dòng)后,由該程序的主線程來(lái)初始化共享數(shù)據(jù)隊(duì)列并創(chuàng)建讀線程和寫(xiě)線程,該共享數(shù)據(jù)隊(duì)列中的元素為寫(xiě)入數(shù)據(jù)的指針,共享數(shù)據(jù)隊(duì)列最大長(zhǎng)度為M,共享數(shù)據(jù)隊(duì)列當(dāng)前元素個(gè)數(shù)為K,K=0。
(2)當(dāng)程序需要對(duì)該共享數(shù)據(jù)隊(duì)列進(jìn)行寫(xiě)操作時(shí),主線程調(diào)用該共享數(shù)據(jù)隊(duì)列的寫(xiě)線程,該寫(xiě)線程操作的時(shí)候,檢查K,如果K<M,寫(xiě)線程執(zhí)行隊(duì)列的push操作,即把要寫(xiě)的數(shù)據(jù)插入到共享數(shù)據(jù)隊(duì)列的寫(xiě)端,并執(zhí)行K++;如果K>=M,返回NULL,表示共享數(shù)據(jù)隊(duì)列已經(jīng)滿了,本次寫(xiě)入失敗,可以根據(jù)自身需要進(jìn)行等待或者輪詢。
(3)當(dāng)程序需要對(duì)該共享數(shù)據(jù)隊(duì)列進(jìn)行讀操作時(shí),主線程調(diào)用該共享數(shù)據(jù)隊(duì)列的讀線程,該讀線程操作的時(shí)候,檢查K,如果K>0,讀線程執(zhí)行隊(duì)列的pop操作,即從共享數(shù)據(jù)隊(duì)列的讀端讀取一個(gè)元素,并執(zhí)行K--;如果K<=0,返回NULL,表示共享數(shù)據(jù)隊(duì)列已經(jīng)空了,即當(dāng)前無(wú)數(shù)據(jù)可讀,可以根據(jù)自身需要進(jìn)行等待或者輪詢。
實(shí)施例
假如共享數(shù)據(jù)隊(duì)列的初始最大長(zhǎng)度為M=10,共享數(shù)據(jù)隊(duì)列當(dāng)前的元素個(gè)數(shù)K=0
例1:寫(xiě)入
檢查K=0<M=10,所以可以執(zhí)行寫(xiě)入,并且執(zhí)行K++,此時(shí)K=1
例2:讀取
檢查K=1>0,執(zhí)行讀取操作,并且執(zhí)行K--,此時(shí)K=0。