本發(fā)明涉及數(shù)據(jù)存儲(chǔ)領(lǐng)域,更具體地說,涉及一種內(nèi)存管理裝置和方法。
背景技術(shù):
提高硬盤寫入IO的方式無(wú)疑是批量順序?qū)懀瑹o(wú)論是在業(yè)界輪行的分布式文件系統(tǒng)或數(shù)據(jù),HBase,GFS和HDFS,還是以磁盤文件為持久化方式的消息隊(duì)列Kafka都采用了在內(nèi)存緩存數(shù)據(jù)然后再批量寫入的策略。這一個(gè)策略的性能核心就是內(nèi)存中緩沖區(qū)的設(shè)計(jì)。然而,為了滿足讀寫同步,必須要保證:(1)寫滿不寫;(2)讀空不讀(3)不丟失數(shù)據(jù)(4)不讀重復(fù)數(shù)據(jù)。為了達(dá)到這一目的,最常用的方式是JDK自帶的LinkedBlockingQueue,是一個(gè)帶鎖的消息隊(duì)列,寫入和讀出時(shí)加鎖,在滿足以上條件時(shí),卻占用了極大的系統(tǒng)資源,成為很多對(duì)吞吐量要求很高的程序的性能瓶頸。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明要解決的技術(shù)問題在于如何避免系統(tǒng)資源的過多占用,且保證足夠的讀寫速度;針對(duì)該技術(shù)問題,提供一種內(nèi)存管理裝置,包括:
創(chuàng)建模塊,用于創(chuàng)建定長(zhǎng)數(shù)組,為定長(zhǎng)數(shù)組的各元素分配存儲(chǔ)空間,所述定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu);
設(shè)置模塊,用于設(shè)置一個(gè)基于所述環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;
寫數(shù)據(jù)模塊,用于當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取所述標(biāo)識(shí)指針,向所述標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù);使所述標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放所述標(biāo)識(shí)指針;
讀數(shù)據(jù)模塊,用于當(dāng)讀數(shù)據(jù)時(shí),基于所述環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置;
確保模塊,用于在所述寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確保所述標(biāo)識(shí)指針與所述當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。
可選的,所述定長(zhǎng)數(shù)組的元素的數(shù)量為2的指數(shù)倍。
可選的,所述寫數(shù)據(jù)模塊還用于:通過多線程分別執(zhí)行CAS控制指令競(jìng)爭(zhēng)獲取所述標(biāo)識(shí)指針。
可選的,所述確保模塊還用于:
設(shè)置一個(gè)大于等于1的寫操作等待閾值;
在寫數(shù)據(jù)時(shí),當(dāng)寫位置差值小于等于所述寫操作等待閾值時(shí),暫停寫數(shù)據(jù)操作,所述寫位置差值為所述標(biāo)識(shí)指針沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與所述當(dāng)前讀取位置之間的位置差值;
監(jiān)控所述寫位置差值,并在所述寫位置差值大于所述寫操作等待閾值時(shí)重啟寫數(shù)據(jù)操作。
可選的,所述確保模塊還用于:
設(shè)置一個(gè)大于等于1的讀操作等待閾值;
在讀數(shù)據(jù)時(shí),當(dāng)讀位置差值小于等于所述讀操作等待閾值時(shí),暫停讀數(shù)據(jù)操作,所述讀位置差值為所述當(dāng)前讀取位置沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與所述標(biāo)識(shí)指針之間的位置差值;
監(jiān)控所述讀位置差值,并在所述讀位置差值大于所述讀操作等待閾值時(shí)重啟讀數(shù)據(jù)操作。
此外,還提供一種內(nèi)存管理方法,包括:
創(chuàng)建定長(zhǎng)數(shù)組,并為定長(zhǎng)數(shù)組的各元素分配存儲(chǔ)空間,所述定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu);
設(shè)置一個(gè)基于所述環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;
當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取所述標(biāo)識(shí)指針,向所述標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù);使所述標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放所述標(biāo)識(shí)指針;
當(dāng)讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置;
在所述寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確保所述標(biāo)識(shí)指針與所述當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。
可選的,所述定長(zhǎng)數(shù)組的元素的數(shù)量為2的指數(shù)倍。
可選的,所述當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取所述標(biāo)識(shí)指針包括:通過多線程分別執(zhí)行CAS控制指令競(jìng)爭(zhēng)獲取所述標(biāo)識(shí)指針。
可選的,所述在寫數(shù)據(jù)過程中,確定所述標(biāo)識(shí)指針與所述當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置包括:
設(shè)置一個(gè)大于等于1的寫操作等待閾值;
在寫數(shù)據(jù)時(shí),當(dāng)寫位置差值小于等于所述寫操作等待閾值時(shí),暫停寫數(shù)據(jù)操作,所述寫位置差值為所述標(biāo)識(shí)指針沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與所述當(dāng)前讀取位置之間的位置差值;
監(jiān)控所述寫位置差值,并在所述寫位置差值大于所述寫操作等待閾值時(shí)重啟寫數(shù)據(jù)操作。
可選的,所述在讀數(shù)據(jù)過程中,確定所述標(biāo)識(shí)指針與所述當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置包括:
設(shè)置一個(gè)大于等于1的讀操作等待閾值;
在讀數(shù)據(jù)時(shí),當(dāng)讀位置差值小于等于所述讀操作等待閾值時(shí),暫停讀數(shù)據(jù)操作,所述讀位置差值為所述當(dāng)前讀取位置沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與所述標(biāo)識(shí)指針之間的位置差值;
監(jiān)控所述讀位置差值,并在所述讀位置差值大于所述讀操作等待閾值時(shí)重啟讀數(shù)據(jù)操作。
有益效果
本發(fā)明提供了一種內(nèi)存管理裝置和方法,創(chuàng)建定長(zhǎng)數(shù)組,為定長(zhǎng)數(shù)組的各元素分配存儲(chǔ)空間,定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu),設(shè)置一個(gè)基于環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,像標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù),讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),在讀寫的過程中,確保標(biāo)識(shí)指針和當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。通過本發(fā)明的實(shí)施,使用標(biāo)識(shí)指針來進(jìn)行數(shù)據(jù)的寫入,且保證讀寫過程中標(biāo)識(shí)指針和當(dāng)前寫入位置不重疊,從而滿足了讀寫同步,節(jié)約了大量的系統(tǒng)資源。
附圖說明
下面將結(jié)合附圖及實(shí)施例對(duì)本發(fā)明作進(jìn)一步說明,附圖中:
圖1為本發(fā)明第一實(shí)施例提供的一種內(nèi)存管理裝置組成示意圖;
圖2為本發(fā)明第一實(shí)施例提供的一種環(huán)形隊(duì)列示意圖;
圖3為本發(fā)明第二實(shí)施例提供的一種寫位置差值的表現(xiàn)方式示意圖;
圖4為本發(fā)明第二實(shí)施例提供的一種讀位置差值的表現(xiàn)方式示意圖;
圖5為本發(fā)明第三實(shí)施例提供的一種內(nèi)存管理方法流程圖;
圖6為本發(fā)明第四實(shí)施例提供的一種內(nèi)存管理方法流程圖。
具體實(shí)施方式
應(yīng)當(dāng)理解,此處所描述的具體實(shí)施例僅僅用以解釋本發(fā)明,并不用于限定本發(fā)明。
第一實(shí)施例
請(qǐng)參考圖1,圖1為本發(fā)明第一實(shí)施例提供的一種內(nèi)存管理裝置組成示意圖,包括:
創(chuàng)建模塊101,用于創(chuàng)建定長(zhǎng)數(shù)組,為定長(zhǎng)數(shù)組的各元素分配存儲(chǔ)空間,該定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu);
設(shè)置模塊102,用于設(shè)置一個(gè)基于環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;
寫數(shù)據(jù)模塊103,用于當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,向標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù);使標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放標(biāo)識(shí)指針;
讀數(shù)據(jù)模塊104,用于當(dāng)讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置;
確保模塊105,用于在寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確保標(biāo)識(shí)指針與當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。
本實(shí)施例中的定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu),環(huán)形隊(duì)列是在實(shí)際編程中極為有用的數(shù)據(jù)結(jié)構(gòu),它有如下特點(diǎn):
它是一個(gè)首尾相連的FIFO(First In First Out,先進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),采用數(shù)組的線性空間,數(shù)據(jù)組織簡(jiǎn)單。能很快知道隊(duì)列是否是滿或是空。能以很快的速度來存取數(shù)據(jù)。
因?yàn)楹?jiǎn)單高效的原因,甚至在硬件上都實(shí)現(xiàn)了環(huán)形隊(duì)列。
環(huán)形隊(duì)列廣泛應(yīng)用于網(wǎng)絡(luò)數(shù)據(jù)收發(fā),和不同程序間數(shù)據(jù)交換(比如內(nèi)核與應(yīng)用程序大量交換數(shù)據(jù),從硬件接收大量數(shù)據(jù))均使用了環(huán)形隊(duì)列。
實(shí)際上,內(nèi)存并沒有環(huán)形結(jié)構(gòu),因此環(huán)形隊(duì)列實(shí)際上是數(shù)組的線性空間來實(shí)現(xiàn)。當(dāng)數(shù)據(jù)到了尾部時(shí),它將回到0位置處理。這個(gè)轉(zhuǎn)回是通過取模操作來執(zhí)行的。因此,環(huán)形隊(duì)列邏輯上是將數(shù)組元素q[0]與q[n-1]連接,形成一個(gè)存放隊(duì)列的環(huán)形空間。請(qǐng)參考圖2,圖2示出了一種具有八個(gè)元素的環(huán)形隊(duì)列形態(tài)的定長(zhǎng)數(shù)組,其中q[n-1]即為q[7]。
在實(shí)際使用中,環(huán)形隊(duì)列并沒有首尾之分,由于首尾相接,環(huán)形隊(duì)列中所存儲(chǔ)的數(shù)據(jù)也沒有前后的區(qū)別;然而,環(huán)形隊(duì)列的數(shù)據(jù)讀寫是有一定的方向的,雖然這個(gè)方向?qū)τ诓煌沫h(huán)形隊(duì)列而言是不一定的,但是對(duì)于某個(gè)特定的環(huán)形隊(duì)列而言,這個(gè)方向是唯一確定的;用戶所寫入的數(shù)據(jù)是以這個(gè)確定的方向?qū)懭?,用戶讀取數(shù)據(jù)也同樣是以這個(gè)確定的方向進(jìn)行讀取。
定長(zhǎng)數(shù)組的含義在于,數(shù)組的長(zhǎng)度,或者說數(shù)組中允許存取元素的空間的數(shù)量是固定的;請(qǐng)繼續(xù)參考圖2,圖2所示出的環(huán)形數(shù)組,其數(shù)組的長(zhǎng)度是8,數(shù)組中允許存取元素的空間的數(shù)量也是8,以其中任意一個(gè)存取元素的空間作為起始元素q[0],以特定方向,圖2中的為逆時(shí)針方向,各元素的編號(hào)分別為q[1]、q[2]、q[3]、q[4]、q[5]、q[6]、q[7];當(dāng)定長(zhǎng)數(shù)組的長(zhǎng)度不是8,是更大或者更小的數(shù)時(shí),與為8的情況類似;如不特殊說明,本實(shí)施例中所列舉的定長(zhǎng)數(shù)組的長(zhǎng)度均是8。
設(shè)置模塊102用于設(shè)置一個(gè)基于該環(huán)形隊(duì)列的標(biāo)識(shí)指針,用于標(biāo)識(shí)下一寫入位置。在本實(shí)施例中,在定長(zhǎng)數(shù)組中寫入數(shù)據(jù)是通過標(biāo)識(shí)指針來指引的,即寫入數(shù)據(jù)是在標(biāo)識(shí)指針?biāo)诘奈恢脤懭耄粯?biāo)識(shí)指針的邏輯是,在當(dāng)前的位置寫完數(shù)據(jù)后,會(huì)進(jìn)行自增,即在環(huán)形隊(duì)列的寫數(shù)據(jù)方向上自行移動(dòng),然后,在標(biāo)識(shí)指針?biāo)幍男碌奈恢蒙侠^續(xù)寫入數(shù)據(jù)。標(biāo)識(shí)指針?biāo)加玫南到y(tǒng)資源極少,且無(wú)需用戶自行操作,它會(huì)自動(dòng)在環(huán)形隊(duì)列中移動(dòng)。
寫數(shù)據(jù)模塊103用于當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,向標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù)。當(dāng)不止一個(gè)數(shù)據(jù)要寫入時(shí),在同一個(gè)存儲(chǔ)位置一般只存儲(chǔ)一個(gè)對(duì)象寫入的數(shù)據(jù),那么,不同的對(duì)象之間就需要通過競(jìng)爭(zhēng),來獲取標(biāo)識(shí)指針,或者說獲取標(biāo)識(shí)指針的使用權(quán),使該對(duì)象能夠在標(biāo)識(shí)指針?biāo)诘奈恢脤懭霐?shù)據(jù)。
在當(dāng)前位置的數(shù)據(jù)寫完之后,標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放標(biāo)識(shí)指針。其中,釋放標(biāo)識(shí)指針,或者說釋放標(biāo)識(shí)指針的控制權(quán),在前一次的數(shù)據(jù)寫入完成后,釋放的標(biāo)識(shí)指針會(huì)自動(dòng)的沿著數(shù)據(jù)寫入的方向跳轉(zhuǎn)到下一寫入位置,等待下一數(shù)據(jù)的寫入。
讀數(shù)據(jù)模塊104用于當(dāng)讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置?;诃h(huán)形隊(duì)列依次順序讀取數(shù)據(jù),指的就是在環(huán)形隊(duì)列中,數(shù)據(jù)的讀取是按照一個(gè)特定的方向來的,對(duì)于一個(gè)特定的環(huán)形隊(duì)列而言,這個(gè)方向是確定的,與寫數(shù)據(jù)的方向一致。
確保模塊105,用于在寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確定標(biāo)識(shí)指針和當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。由于在數(shù)據(jù)讀寫的過程中,有著寫滿不寫,讀空不讀的要求,即環(huán)形隊(duì)列中即將在下一個(gè)位置寫數(shù)據(jù)時(shí),該下一個(gè)位置的數(shù)據(jù)仍然未被讀取,那么就不應(yīng)再寫;以及在環(huán)形隊(duì)列中,即將讀取下一位置的數(shù)據(jù)時(shí),下一位置的數(shù)據(jù)為空或者尚未寫完,那么就不應(yīng)再讀。如果在下一位置的數(shù)據(jù)仍未被讀取時(shí)寫入數(shù)據(jù)的話,那么就會(huì)導(dǎo)致數(shù)據(jù)丟失;如果在下一位置的數(shù)據(jù)為空或者尚未寫完時(shí)讀取數(shù)據(jù)的話,就會(huì)讀取到空的數(shù)據(jù),浪費(fèi)系統(tǒng)資源和時(shí)間。
而正常而言,數(shù)據(jù)讀寫的過程中,一個(gè)數(shù)據(jù)總是先被寫入之后,再被讀取,換言之,對(duì)于一個(gè)數(shù)據(jù)而言,寫入在先,讀取在后,在環(huán)形隊(duì)列中,總是先寫的數(shù)據(jù)先被讀取,那么,在滿足寫滿不寫,讀空不讀時(shí),標(biāo)識(shí)指針和當(dāng)前讀取位置總是處于環(huán)形隊(duì)列中的不同位置的。
本實(shí)施例提供了一種內(nèi)存管理裝置,包括創(chuàng)建模塊、設(shè)置模塊、寫數(shù)據(jù)模塊、讀數(shù)據(jù)模塊以及確保模塊,通過實(shí)施例的實(shí)施,實(shí)現(xiàn)了使用標(biāo)識(shí)指針來進(jìn)行數(shù)據(jù)的寫入,且保證讀寫過程中標(biāo)識(shí)指針和當(dāng)前寫入位置不重疊,滿足和讀寫同步,節(jié)約了大量的系統(tǒng)資源。
第二實(shí)施例
請(qǐng)繼續(xù)參考圖1,圖1為本發(fā)明第二實(shí)施例提供的一種內(nèi)存管理裝置組成示意圖,包括:
創(chuàng)建模塊101,用于創(chuàng)建定長(zhǎng)數(shù)組,為定長(zhǎng)數(shù)組的各元素分配存儲(chǔ)空間,該定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu);
設(shè)置模塊102,用于設(shè)置一個(gè)基于環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;
寫數(shù)據(jù)模塊103,用于當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,向標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù);使標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放標(biāo)識(shí)指針;
讀數(shù)據(jù)模塊104,用于當(dāng)讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置;
確保模塊105,用于在寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確保標(biāo)識(shí)指針與當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。
其中,在本實(shí)施例中,關(guān)于定長(zhǎng)數(shù)組的大小的選擇方面有一定的要求,由于在環(huán)形隊(duì)列中會(huì)用到取余操作,在大部分處理器上,取余操作并不高效,因此,在本實(shí)施例中,定長(zhǎng)數(shù)組的元素的數(shù)量為2的指數(shù)倍,這樣,計(jì)算余數(shù)只需要通過為操作index&(size-1)就能夠得到實(shí)際的index。對(duì)外只有一個(gè)變量,那就是隊(duì)尾元素的下標(biāo):cursor,這也避免了對(duì)head/tail這兩個(gè)變量的操作和協(xié)同。
在本實(shí)施例中,寫數(shù)據(jù)模塊103還用于:通過多線程分別執(zhí)行CAS控制指令競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針。在實(shí)際寫數(shù)據(jù)的過程中,在同一時(shí)間可能并不止有一個(gè)即將執(zhí)行的寫入操作,即進(jìn)行寫操作的對(duì)象并不止一個(gè);如果兩個(gè)或以上的對(duì)象同時(shí)都想寫入數(shù)據(jù),則他們會(huì)同時(shí)執(zhí)行CAS指令,具體為CAS(slot,slot+1),然后執(zhí)行成功的競(jìng)爭(zhēng)成功,獲取標(biāo)識(shí)指針,或者說是獲取標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置的存儲(chǔ)權(quán),獲取該存儲(chǔ)權(quán)的對(duì)象就可以將數(shù)據(jù)寫入,其他的未獲取成功的則需要繼續(xù)下一個(gè)CAS指令申請(qǐng)之后的標(biāo)識(shí)指針。在這一過程中,一般并不需要用到鎖,使用的是系統(tǒng)的CAS指令。
在很多時(shí)候會(huì)有多個(gè)對(duì)象去搶數(shù)組上的同一個(gè)位置,在一般的java程序中,是通過加鎖來實(shí)現(xiàn),但本實(shí)施例是通過CAS來實(shí)現(xiàn)的,多個(gè)會(huì)去競(jìng)爭(zhēng),但不會(huì)存在兩個(gè)同時(shí)搶到,搶不到的就搶下一個(gè)位置。讀寫雙方都要檢查對(duì)方的位置,防止超過對(duì)方。在本實(shí)施例中,檢查的策略可以包括主動(dòng)檢查,比如按照一定的時(shí)間間隔周期性的檢查對(duì)方的位置,或者等待對(duì)方的通知,如設(shè)置一道指令,令對(duì)方讀/寫到環(huán)形隊(duì)列的某一位置即發(fā)送通知。
在本實(shí)施例中,確保模塊105還用于:設(shè)置一個(gè)大于等于1的寫操作等待閾值;
在寫數(shù)據(jù)時(shí),當(dāng)寫位置差值小于等于寫操作等待閾值時(shí),暫停寫數(shù)據(jù)操作,其中,寫位置差值為標(biāo)識(shí)指針沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與當(dāng)前讀取位置之間的位置差值;
監(jiān)控寫位置差值,并在寫位置差值大于寫操作等待閾值時(shí)重啟寫數(shù)據(jù)操作。
也就是說,確保模塊105為了確保在寫數(shù)據(jù)時(shí),確保標(biāo)識(shí)指針與當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置,首先,設(shè)置一個(gè)大于等于1的寫操作等待閾值,而寫位置差值則是標(biāo)識(shí)指針,在沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與當(dāng)前讀取位置之間的位置差值;通俗的講,就是標(biāo)識(shí)指針與當(dāng)前讀取位置之間的間隔,而這個(gè)間隔是從標(biāo)識(shí)指針到下一寫入位置方向上所得的,請(qǐng)參考圖3,圖3示出了一種寫位置差值的計(jì)算方式,或者說是表現(xiàn)方式。從圖3中可以看出,讀數(shù)據(jù)的方向和寫數(shù)據(jù)的方向是一致的,當(dāng)寫數(shù)據(jù)的速度過快時(shí),標(biāo)識(shí)指針的位置就可能達(dá)到或者超過當(dāng)前讀取位置。因此,設(shè)置一個(gè)寫操作等待閾值,這個(gè)閾值至少為1,即標(biāo)識(shí)指針與當(dāng)前讀取位置之間至少間隔一個(gè)位置,而具體的寫操作等待閾值可以基于環(huán)形隊(duì)列的長(zhǎng)度、數(shù)據(jù)量的大小、讀寫的速度等等參數(shù)進(jìn)行設(shè)置;當(dāng)標(biāo)識(shí)指針?biāo)幍奈恢门c當(dāng)前讀取位置之間的差值小于或等于寫操作等待閾值時(shí),暫停寫數(shù)據(jù)操作,即不再進(jìn)行寫數(shù)據(jù)操作;與此同時(shí),實(shí)時(shí)監(jiān)控寫位置差值,在寫位置差值大于寫操作等待閾值時(shí),重啟寫數(shù)據(jù)操作。
在本實(shí)施例中,確保模塊105還用于:設(shè)置一個(gè)大于等于1的讀操作等待閾值;
在讀數(shù)據(jù)時(shí),當(dāng)讀位置差值小于等于讀操作等待閾值時(shí),暫停讀數(shù)據(jù)操作,其中,讀位置差值為當(dāng)前讀取位置沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與標(biāo)識(shí)指針之間的位置差值;
監(jiān)控讀位置差值,并在讀位置差值大于讀操作等待閾值時(shí)重啟讀數(shù)據(jù)操作。
也就是說,確保模塊105為了確保在讀數(shù)據(jù)時(shí),確保標(biāo)識(shí)指針與當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置,首先,設(shè)置一個(gè)大于等于1的讀操作等待閾值,而讀位置差值則是,在沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與標(biāo)識(shí)指針之間的位置差值;通俗的講,就是當(dāng)前讀取位置與標(biāo)識(shí)指針之間的間隔,而這個(gè)間隔是從當(dāng)前讀取位置到下一讀取位置方向上所得的,請(qǐng)參考圖4,圖4示出了一種讀位置差值的計(jì)算方式,或者說是表現(xiàn)方式。從圖4中可以看出,讀數(shù)據(jù)的方向和寫數(shù)據(jù)的方向是一致的,當(dāng)讀數(shù)據(jù)的速度過快時(shí),當(dāng)前讀取位置就可能達(dá)到或超過標(biāo)識(shí)指針?biāo)诘奈恢?。因此,設(shè)置一個(gè)讀操作等待閾值,這個(gè)閾值至少為1,即當(dāng)前讀取位置與標(biāo)識(shí)指針之間至少間隔一個(gè)位置,而具體的讀操作等待閾值可以基于環(huán)形隊(duì)列的長(zhǎng)度、數(shù)據(jù)量的大小、讀寫的速度等等參數(shù)進(jìn)行設(shè)置;當(dāng)當(dāng)前讀取位置與標(biāo)識(shí)指針?biāo)幍奈恢弥g的差值小于或等于讀操作等待閾值時(shí),暫停讀數(shù)據(jù)操作,即不再進(jìn)行讀數(shù)據(jù)操作;與此同時(shí),實(shí)時(shí)監(jiān)控讀位置差值,在讀位置差值大于讀操作等待閾值時(shí),重啟讀數(shù)據(jù)操作。
值得一提的是,在本實(shí)施例中,寫操作和讀操作之間,若偏重于寫操作,即以寫操作為主,那么,應(yīng)該設(shè)置寫操作等待閾值較小,若偏重于讀操作,即以讀操作為主,那么,應(yīng)該設(shè)置讀操作等待閾值較小。由于本實(shí)施例中的數(shù)組是定長(zhǎng)數(shù)組,因此,在為了保證其中一個(gè)效果較好時(shí)設(shè)置更小的讀/寫操作等待閾值時(shí),另一個(gè)寫/讀操作等待閾值就相應(yīng)的設(shè)置為較大,具體如何權(quán)衡可以根據(jù)環(huán)形隊(duì)列的長(zhǎng)度、數(shù)據(jù)量的大小以及讀寫的速度來決定。
此外,由于本實(shí)施例中的基于環(huán)形隊(duì)列的定長(zhǎng)數(shù)組已經(jīng)進(jìn)行了編碼,而讀寫操作一般都是根據(jù)編碼的順序而來,如寫數(shù)據(jù)是從q[0]開始,經(jīng)過q[1]、q[2]等等到q[7],然后再回到q[0]進(jìn)入一個(gè)循環(huán);而讀數(shù)據(jù)亦如是,因此,若是用序號(hào)進(jìn)行寫位置差值和讀位置差值的計(jì)算,那么沿著環(huán)形隊(duì)列的數(shù)據(jù)方向,前者與后者之間的差值應(yīng)該為負(fù)值,因此,本實(shí)施例中的寫位置差值的準(zhǔn)確表述應(yīng)該是,標(biāo)識(shí)指針?biāo)谖恢醚丨h(huán)形隊(duì)列的數(shù)據(jù)方向上與當(dāng)前讀取位置之間間隔的元素的數(shù)目,讀位置差值的準(zhǔn)確表述應(yīng)該是,當(dāng)前讀取位置沿環(huán)形隊(duì)列的數(shù)據(jù)方向上與標(biāo)識(shí)指針?biāo)谖恢弥g間隔的元素的數(shù)目。
本實(shí)施例提供了一種內(nèi)存管理裝置,包括創(chuàng)建模塊、設(shè)置模塊、寫數(shù)據(jù)模塊、讀數(shù)據(jù)模塊以及確保模塊,通過實(shí)施例的實(shí)施,實(shí)現(xiàn)了使用標(biāo)識(shí)指針來進(jìn)行數(shù)據(jù)的寫入,且保證讀寫過程中標(biāo)識(shí)指針和當(dāng)前寫入位置不重疊,滿足和讀寫同步,節(jié)約了大量的系統(tǒng)資源。
第三實(shí)施例
請(qǐng)參考圖5,圖5為本發(fā)明第三實(shí)施例提供的一種內(nèi)存管理方法流程圖,包括:
S501、創(chuàng)建定長(zhǎng)數(shù)組,并為定長(zhǎng)數(shù)組的各元素分配分配存儲(chǔ)空間,所述定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu);
S502、設(shè)置一個(gè)基于環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;
S503、當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,向標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù);使標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放標(biāo)識(shí)指針;
S504、當(dāng)讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置;
其中,在寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確保標(biāo)識(shí)指針與當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。
本實(shí)施例中的定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu),環(huán)形隊(duì)列是在實(shí)際編程中極為有用的數(shù)據(jù)結(jié)構(gòu),它有如下特點(diǎn):
它是一個(gè)首尾相連的FIFO(First In First Out,先進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),采用數(shù)組的線性空間,數(shù)據(jù)組織簡(jiǎn)單。能很快知道隊(duì)列是否是滿或是空。能以很快的速度來存取數(shù)據(jù)。
因?yàn)楹?jiǎn)單高效的原因,甚至在硬件上都實(shí)現(xiàn)了環(huán)形隊(duì)列。
環(huán)形隊(duì)列廣泛應(yīng)用于網(wǎng)絡(luò)數(shù)據(jù)收發(fā),和不同程序間數(shù)據(jù)交換(比如內(nèi)核與應(yīng)用程序大量交換數(shù)據(jù),從硬件接收大量數(shù)據(jù))均使用了環(huán)形隊(duì)列。
實(shí)際上,內(nèi)存并沒有環(huán)形結(jié)構(gòu),因此環(huán)形隊(duì)列實(shí)際上是數(shù)組的線性空間來實(shí)現(xiàn)。當(dāng)數(shù)據(jù)到了尾部時(shí),它將回到0位置處理。這個(gè)轉(zhuǎn)回是通過取模操作來執(zhí)行的。因此,環(huán)形隊(duì)列邏輯上是將數(shù)組元素q[0]與q[n-1]連接,形成一個(gè)存放隊(duì)列的環(huán)形空間。請(qǐng)參考圖2,圖2示出了一種具有八個(gè)元素的環(huán)形隊(duì)列形態(tài)的定長(zhǎng)數(shù)組,其中q[n-1]即為q[7]。
在實(shí)際使用中,環(huán)形隊(duì)列并沒有首尾之分,由于首尾相接,環(huán)形隊(duì)列中所存儲(chǔ)的數(shù)據(jù)也沒有前后的區(qū)別;然而,環(huán)形隊(duì)列的數(shù)據(jù)讀寫是有一定的方向的,雖然這個(gè)方向?qū)τ诓煌沫h(huán)形隊(duì)列而言是不一定的,但是對(duì)于某個(gè)特定的環(huán)形隊(duì)列而言,這個(gè)方向是唯一確定的;用戶所寫入的數(shù)據(jù)是以這個(gè)確定的方向?qū)懭?,用戶讀取數(shù)據(jù)也同樣是以這個(gè)確定的方向進(jìn)行讀取。
定長(zhǎng)數(shù)組的含義在于,數(shù)組的長(zhǎng)度,或者說數(shù)組中允許存取元素的空間的數(shù)量是固定的;請(qǐng)繼續(xù)參考圖2,圖2所示出的環(huán)形數(shù)組,其數(shù)組的長(zhǎng)度是8,數(shù)組中允許存取元素的空間的數(shù)量也是8,以其中任意一個(gè)存取元素的空間作為起始元素q[0],以特定方向,圖2中的為逆時(shí)針方向,各元素的編號(hào)分別為q[1]、q[2]、q[3]、q[4]、q[5]、q[6]、q[7];當(dāng)定長(zhǎng)數(shù)組的長(zhǎng)度不是8,是更大或者更小的數(shù)時(shí),與為8的情況類似;如不特殊說明,本實(shí)施例中所列舉的定長(zhǎng)數(shù)組的長(zhǎng)度均是8。
其中,在本實(shí)施例中,關(guān)于定長(zhǎng)數(shù)組的大小的選擇方面有一定的要求,由于在環(huán)形隊(duì)列中會(huì)用到取余操作,在大部分處理器上,取余操作并不高效,因此,在本實(shí)施例中,定長(zhǎng)數(shù)組的元素的數(shù)量為2的指數(shù)倍,這樣,計(jì)算余數(shù)只需要通過為操作index&(size-1)就能夠得到實(shí)際的index。對(duì)外只有一個(gè)變量,那就是隊(duì)尾元素的下標(biāo):cursor,這也避免了對(duì)head/tail這兩個(gè)變量的操作和協(xié)同。
S502中,設(shè)置一個(gè)基于該環(huán)形隊(duì)列的標(biāo)識(shí)指針,用于標(biāo)識(shí)下一寫入位置。在本實(shí)施例中,在定長(zhǎng)數(shù)組中寫入數(shù)據(jù)是通過標(biāo)識(shí)指針來指引的,即寫入數(shù)據(jù)是在標(biāo)識(shí)指針?biāo)诘奈恢脤懭?;?biāo)識(shí)指針的邏輯是,在當(dāng)前的位置寫完數(shù)據(jù)后,會(huì)進(jìn)行自增,即在環(huán)形隊(duì)列的寫數(shù)據(jù)方向上自行移動(dòng),然后,在標(biāo)識(shí)指針?biāo)幍男碌奈恢蒙侠^續(xù)寫入數(shù)據(jù)。標(biāo)識(shí)指針?biāo)加玫南到y(tǒng)資源極少,且無(wú)需用戶自行操作,它會(huì)自動(dòng)在環(huán)形隊(duì)列中移動(dòng)。
S503中,當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,向標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù)。當(dāng)不止一個(gè)數(shù)據(jù)要寫入時(shí),在同一個(gè)存儲(chǔ)位置一般只存儲(chǔ)一個(gè)對(duì)象寫入的數(shù)據(jù),那么,不同的對(duì)象之間就需要通過競(jìng)爭(zhēng),來獲取標(biāo)識(shí)指針,或者說獲取標(biāo)識(shí)指針的使用權(quán),使該對(duì)象能夠在標(biāo)識(shí)指針?biāo)诘奈恢脤懭霐?shù)據(jù)。
通過多線程分別執(zhí)行CAS控制指令競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針。在實(shí)際寫數(shù)據(jù)的過程中,在同一時(shí)間可能并不止有一個(gè)即將執(zhí)行的寫入操作,即進(jìn)行寫操作的對(duì)象并不止一個(gè);如果兩個(gè)或以上的對(duì)象同時(shí)都想寫入數(shù)據(jù),則他們會(huì)同時(shí)執(zhí)行CAS指令,具體為CAS(slot,slot+1),然后執(zhí)行成功的競(jìng)爭(zhēng)成功,獲取標(biāo)識(shí)指針,或者說是獲取標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置的存儲(chǔ)權(quán),獲取該存儲(chǔ)權(quán)的對(duì)象就可以將數(shù)據(jù)寫入,其他的未獲取成功的則需要繼續(xù)下一個(gè)CAS指令申請(qǐng)之后的標(biāo)識(shí)指針。在這一過程中,一般并不需要用到鎖,使用的是系統(tǒng)的CAS指令。
在很多時(shí)候會(huì)有多個(gè)對(duì)象去搶數(shù)組上的同一個(gè)位置,在一般的java程序中,是通過加鎖來實(shí)現(xiàn),但本實(shí)施例是通過CAS來實(shí)現(xiàn)的,多個(gè)會(huì)去競(jìng)爭(zhēng),但不會(huì)存在兩個(gè)同時(shí)搶到,搶不到的就搶下一個(gè)位置。讀寫雙方都要檢查對(duì)方的位置,防止超過對(duì)方。在本實(shí)施例中,檢查的策略可以包括主動(dòng)檢查,比如按照一定的時(shí)間間隔周期性的檢查對(duì)方的位置,或者等待對(duì)方的通知,如設(shè)置一道指令,令對(duì)方讀/寫到環(huán)形隊(duì)列的某一位置即發(fā)送通知。
在當(dāng)前位置的數(shù)據(jù)寫完之后,標(biāo)識(shí)指針跳轉(zhuǎn)到下一寫入位置,釋放標(biāo)識(shí)指針。其中,釋放標(biāo)識(shí)指針,或者說釋放標(biāo)識(shí)指針的控制權(quán),在前一次的數(shù)據(jù)寫入完成后,釋放的標(biāo)識(shí)指針會(huì)自動(dòng)的沿著數(shù)據(jù)寫入的方向跳轉(zhuǎn)到下一寫入位置,等待下一數(shù)據(jù)的寫入。
S504中,當(dāng)讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),并更新當(dāng)前讀取位置?;诃h(huán)形隊(duì)列依次順序讀取數(shù)據(jù),指的就是在環(huán)形隊(duì)列中,數(shù)據(jù)的讀取是按照一個(gè)特定的方向來的,對(duì)于一個(gè)特定的環(huán)形隊(duì)列而言,這個(gè)方向是確定的,與寫數(shù)據(jù)的方向一致。
在寫數(shù)據(jù)和讀數(shù)據(jù)的過程中,確定標(biāo)識(shí)指針和當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。由于在數(shù)據(jù)讀寫的過程中,有著寫滿不寫,讀空不讀的要求,即環(huán)形隊(duì)列中即將在下一個(gè)位置寫數(shù)據(jù)時(shí),該下一個(gè)位置的數(shù)據(jù)仍然未被讀取,那么就不應(yīng)再寫;以及在環(huán)形隊(duì)列中,即將讀取下一位置的數(shù)據(jù)時(shí),下一位置的數(shù)據(jù)為空或者尚未寫完,那么就不應(yīng)再讀。如果在下一位置的數(shù)據(jù)仍未被讀取時(shí)寫入數(shù)據(jù)的話,那么就會(huì)導(dǎo)致數(shù)據(jù)丟失;如果在下一位置的數(shù)據(jù)為空或者尚未寫完時(shí)讀取數(shù)據(jù)的話,就會(huì)讀取到空的數(shù)據(jù),浪費(fèi)系統(tǒng)資源和時(shí)間。
而正常而言,數(shù)據(jù)讀寫的過程中,一個(gè)數(shù)據(jù)總是先被寫入之后,再被讀取,換言之,對(duì)于一個(gè)數(shù)據(jù)而言,寫入在先,讀取在后,在環(huán)形隊(duì)列中,總是先寫的數(shù)據(jù)先被讀取,那么,在滿足寫滿不寫,讀空不讀時(shí),標(biāo)識(shí)指針和當(dāng)前讀取位置總是處于環(huán)形隊(duì)列中的不同位置的。
本實(shí)施例中,為了確保標(biāo)識(shí)指針和當(dāng)前讀取位置總是處于環(huán)形隊(duì)列中的不同位置,還可以包括:
設(shè)置一個(gè)大于等于1的寫操作等待閾值;
在寫數(shù)據(jù)時(shí),當(dāng)寫位置差值小于等于寫操作等待閾值時(shí),暫停寫數(shù)據(jù)操作,其中,寫位置差值為標(biāo)識(shí)指針沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與當(dāng)前讀取位置之間的位置差值;
監(jiān)控寫位置差值,并在寫位置差值大于寫操作等待閾值時(shí)重啟寫數(shù)據(jù)操作。
也就是說,首先,設(shè)置一個(gè)大于等于1的寫操作等待閾值,而寫位置差值則是標(biāo)識(shí)指針,在沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與當(dāng)前讀取位置之間的位置差值;通俗的講,就是標(biāo)識(shí)指針與當(dāng)前讀取位置之間的間隔,而這個(gè)間隔是從標(biāo)識(shí)指針到下一寫入位置方向上所得的,請(qǐng)參考圖3,圖3示出了一種寫位置差值的計(jì)算方式,或者說是表現(xiàn)方式。從圖3中可以看出,讀數(shù)據(jù)的方向和寫數(shù)據(jù)的方向是一致的,當(dāng)寫數(shù)據(jù)的速度過快時(shí),標(biāo)識(shí)指針的位置就可能達(dá)到或者超過當(dāng)前讀取位置。因此,設(shè)置一個(gè)寫操作等待閾值,這個(gè)閾值至少為1,即標(biāo)識(shí)指針與當(dāng)前讀取位置之間至少間隔一個(gè)位置,而具體的寫操作等待閾值可以基于環(huán)形隊(duì)列的長(zhǎng)度、數(shù)據(jù)量的大小、讀寫的速度等等參數(shù)進(jìn)行設(shè)置;當(dāng)標(biāo)識(shí)指針?biāo)幍奈恢门c當(dāng)前讀取位置之間的差值小于或等于寫操作等待閾值時(shí),暫停寫數(shù)據(jù)操作,即不再進(jìn)行寫數(shù)據(jù)操作;與此同時(shí),實(shí)時(shí)監(jiān)控寫位置差值,在寫位置差值大于寫操作等待閾值時(shí),重啟寫數(shù)據(jù)操作。
本實(shí)施例中,為了確保標(biāo)識(shí)指針和當(dāng)前讀取位置總是處于環(huán)形隊(duì)列中的不同位置,還可以包括:
設(shè)置一個(gè)大于等于1的讀操作等待閾值;
在讀數(shù)據(jù)時(shí),當(dāng)讀位置差值小于等于讀操作等待閾值時(shí),暫停讀數(shù)據(jù)操作,其中,讀位置差值為當(dāng)前讀取位置沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與標(biāo)識(shí)指針之間的位置差值;
監(jiān)控讀位置差值,并在讀位置差值大于讀操作等待閾值時(shí)重啟讀數(shù)據(jù)操作。
也就是說,首先,設(shè)置一個(gè)大于等于1的讀操作等待閾值,而讀位置差值則是,在沿著環(huán)形隊(duì)列的數(shù)據(jù)方向上與標(biāo)識(shí)指針之間的位置差值;通俗的講,就是當(dāng)前讀取位置與標(biāo)識(shí)指針之間的間隔,而這個(gè)間隔是從當(dāng)前讀取位置到下一讀取位置方向上所得的,請(qǐng)參考圖4,圖4示出了一種讀位置差值的計(jì)算方式,或者說是表現(xiàn)方式。從圖4中可以看出,讀數(shù)據(jù)的方向和寫數(shù)據(jù)的方向是一致的,當(dāng)讀數(shù)據(jù)的速度過快時(shí),當(dāng)前讀取位置就可能達(dá)到或超過標(biāo)識(shí)指針?biāo)诘奈恢谩R虼?,設(shè)置一個(gè)讀操作等待閾值,這個(gè)閾值至少為1,即當(dāng)前讀取位置與標(biāo)識(shí)指針之間至少間隔一個(gè)位置,而具體的讀操作等待閾值可以基于環(huán)形隊(duì)列的長(zhǎng)度、數(shù)據(jù)量的大小、讀寫的速度等等參數(shù)進(jìn)行設(shè)置;當(dāng)當(dāng)前讀取位置與標(biāo)識(shí)指針?biāo)幍奈恢弥g的差值小于或等于讀操作等待閾值時(shí),暫停讀數(shù)據(jù)操作,即不再進(jìn)行讀數(shù)據(jù)操作;與此同時(shí),實(shí)時(shí)監(jiān)控讀位置差值,在讀位置差值大于讀操作等待閾值時(shí),重啟讀數(shù)據(jù)操作。
值得一提的是,在本實(shí)施例中,寫操作和讀操作之間,若偏重于寫操作,即以寫操作為主,那么,應(yīng)該設(shè)置寫操作等待閾值較小,若偏重于讀操作,即以讀操作為主,那么,應(yīng)該設(shè)置讀操作等待閾值較小。由于本實(shí)施例中的數(shù)組是定長(zhǎng)數(shù)組,因此,在為了保證其中一個(gè)效果較好時(shí)設(shè)置更小的讀/寫操作等待閾值時(shí),另一個(gè)寫/讀操作等待閾值就相應(yīng)的設(shè)置為較大,具體如何權(quán)衡可以根據(jù)環(huán)形隊(duì)列的長(zhǎng)度、數(shù)據(jù)量的大小以及讀寫的速度來決定。
本實(shí)施例提供了一種內(nèi)存管理方法,創(chuàng)建定長(zhǎng)數(shù)組,為定長(zhǎng)數(shù)組的各元素分配存儲(chǔ)空間,定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu),設(shè)置一個(gè)基于環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;當(dāng)寫數(shù)據(jù)時(shí),通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,像標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù),讀數(shù)據(jù)時(shí),基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),在讀寫的過程中,確保標(biāo)識(shí)指針和當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。通過本發(fā)明的實(shí)施,使用標(biāo)識(shí)指針來進(jìn)行數(shù)據(jù)的寫入,且保證讀寫過程中標(biāo)識(shí)指針和當(dāng)前寫入位置不重疊,從而滿足了讀寫同步,節(jié)約了大量的系統(tǒng)資源。
第四實(shí)施例
請(qǐng)參考圖6,圖6為本發(fā)明第四實(shí)施例提供的一種內(nèi)存管理方法流程圖。
本實(shí)施例以生產(chǎn)者和消費(fèi)者為例,對(duì)數(shù)據(jù)的讀寫做進(jìn)一步說明,其中生產(chǎn)者一般作為寫入數(shù)據(jù)的對(duì)象,而消費(fèi)者則作為讀取數(shù)據(jù)的對(duì)象。
S601、創(chuàng)建定長(zhǎng)數(shù)組,為定長(zhǎng)數(shù)組的個(gè)元素分配存儲(chǔ)空間,定長(zhǎng)數(shù)組使用環(huán)形隊(duì)列數(shù)據(jù)結(jié)構(gòu);
S602、設(shè)置一個(gè)基于環(huán)形隊(duì)列的用于標(biāo)識(shí)下一寫入位置的標(biāo)識(shí)指針;
S603、生產(chǎn)者通過競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針,向標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置寫入數(shù)據(jù);
S604、消費(fèi)者基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),更新當(dāng)前讀取位置。
其中,生產(chǎn)者和消費(fèi)者讀寫數(shù)據(jù)的過程中,確保標(biāo)識(shí)指針和當(dāng)前讀取位置處于環(huán)形隊(duì)列中的不同位置。
在實(shí)際使用中,環(huán)形隊(duì)列并沒有首尾之分,由于首尾相接,環(huán)形隊(duì)列中所存儲(chǔ)的數(shù)據(jù)也沒有前后的區(qū)別;然而,環(huán)形隊(duì)列的數(shù)據(jù)讀寫是有一定的方向的,雖然這個(gè)方向?qū)τ诓煌沫h(huán)形隊(duì)列而言是不一定的,但是對(duì)于某個(gè)特定的環(huán)形隊(duì)列而言,這個(gè)方向是唯一確定的;生產(chǎn)者所寫入的數(shù)據(jù)是以這個(gè)確定的方向?qū)懭?,消費(fèi)者讀取數(shù)據(jù)也同樣是以這個(gè)確定的方向進(jìn)行讀取。
關(guān)于定長(zhǎng)數(shù)組的大小的選擇方面有一定的要求,由于在環(huán)形隊(duì)列中會(huì)用到取余操作,在大部分處理器上,取余操作并不高效,因此,在本實(shí)施例中,定長(zhǎng)數(shù)組的元素的數(shù)量為2的指數(shù)倍,這樣,計(jì)算余數(shù)只需要通過為操作index&(size-1)就能夠得到實(shí)際的index。對(duì)外只有一個(gè)變量,那就是隊(duì)尾元素的下標(biāo):cursor,這也避免了對(duì)head/tail這兩個(gè)變量的操作和協(xié)同。
設(shè)置一個(gè)基于該環(huán)形隊(duì)列的標(biāo)識(shí)指針,用于標(biāo)識(shí)下一寫入位置。在本實(shí)施例中,在定長(zhǎng)數(shù)組中寫入數(shù)據(jù)是通過標(biāo)識(shí)指針來指引的,即寫入數(shù)據(jù)是在標(biāo)識(shí)指針?biāo)诘奈恢脤懭耄粯?biāo)識(shí)指針的邏輯是,在當(dāng)前的位置寫完數(shù)據(jù)后,會(huì)進(jìn)行自增,即在環(huán)形隊(duì)列的寫數(shù)據(jù)方向上自行移動(dòng),然后,在標(biāo)識(shí)指針?biāo)幍男碌奈恢蒙侠^續(xù)寫入數(shù)據(jù)。標(biāo)識(shí)指針?biāo)加玫南到y(tǒng)資源極少,且無(wú)需用戶自行操作,它會(huì)自動(dòng)在環(huán)形隊(duì)列中移動(dòng)。
通過多線程分別執(zhí)行CAS控制指令競(jìng)爭(zhēng)獲取標(biāo)識(shí)指針。在實(shí)際寫數(shù)據(jù)的過程中,在同一時(shí)間可能并不止有一個(gè)即將執(zhí)行的寫入操作,即進(jìn)行寫操作的生產(chǎn)者并不止一個(gè);如果兩個(gè)或以上的生產(chǎn)者同時(shí)都想寫入數(shù)據(jù),則他們會(huì)同時(shí)執(zhí)行CAS指令,具體為CAS(slot,slot+1),然后執(zhí)行成功的競(jìng)爭(zhēng)成功,獲取標(biāo)識(shí)指針,或者說是獲取標(biāo)識(shí)指針對(duì)應(yīng)的寫入位置的存儲(chǔ)權(quán),獲取該存儲(chǔ)權(quán)的對(duì)象就可以將數(shù)據(jù)寫入,其他的未獲取成功的生產(chǎn)者則需要繼續(xù)下一個(gè)CAS指令申請(qǐng)之后的標(biāo)識(shí)指針。在這一過程中,一般并不需要用到鎖,使用的是系統(tǒng)的CAS指令。
在很多時(shí)候會(huì)有多個(gè)生產(chǎn)者去搶數(shù)組上的同一個(gè)位置,在一般的java程序中,是通過加鎖來實(shí)現(xiàn),但本實(shí)施例是通過CAS來實(shí)現(xiàn)的,多個(gè)會(huì)去競(jìng)爭(zhēng),但不會(huì)存在兩個(gè)同時(shí)搶到的情況,搶不到的就搶下一個(gè)位置。
消費(fèi)者基于環(huán)形隊(duì)列依次順序讀取數(shù)據(jù),指的就是在環(huán)形隊(duì)列中,數(shù)據(jù)的讀取是按照一個(gè)特定的方向來的,對(duì)于一個(gè)特定的環(huán)形隊(duì)列而言,這個(gè)方向是確定的,與寫數(shù)據(jù)的方向一致。
為了防止生產(chǎn)者生產(chǎn)過快,在環(huán)形隊(duì)列中覆蓋消費(fèi)者的數(shù)據(jù),生成者要對(duì)消費(fèi)者的消費(fèi)情況進(jìn)行跟蹤,即讀取各消費(fèi)者當(dāng)前的讀取位置。
消費(fèi)者需要等待有新元素進(jìn)入方能繼續(xù)讀取,也就是說標(biāo)識(shí)指針大于當(dāng)前讀取位置。等待策略有多種,可以選擇sleep wait可以根據(jù)場(chǎng)景選擇不同的等待策略。
生產(chǎn)者和消費(fèi)者雙方都要檢查對(duì)方的位置,防止超過對(duì)方。在本實(shí)施例中,檢查的策略可以包括主動(dòng)檢查,比如按照一定的時(shí)間間隔周期性的檢查對(duì)方的位置,或者等待對(duì)方的通知,如設(shè)置一道指令,令對(duì)方讀/寫到環(huán)形隊(duì)列的某一位置即發(fā)送通知。比如,消費(fèi)者可以說“當(dāng)你的位置比X大的時(shí)候請(qǐng)告訴我”,說明X之前的節(jié)點(diǎn)已經(jīng)被生產(chǎn)者寫入了數(shù)據(jù),而且消費(fèi)者對(duì)這些節(jié)點(diǎn)的操作是讀而不是寫,因此訪問不用加鎖。
需要說明的是,在本文中,術(shù)語(yǔ)“包括”、“包含”或者其任何其他變體意在涵蓋非排他性的包含,從而使得包括一系列要素的過程、方法、物品或者裝置不僅包括那些要素,而且還包括沒有明確列出的其他要素,或者是還包括為這種過程、方法、物品或者裝置所固有的要素。在沒有更多限制的情況下,由語(yǔ)句“包括一個(gè)……”限定的要素,并不排除在包括該要素的過程、方法、物品或者裝置中還存在另外的相同要素。
上述本發(fā)明實(shí)施例序號(hào)僅僅為了描述,不代表實(shí)施例的優(yōu)劣。
通過以上的實(shí)施方式的描述,本領(lǐng)域的技術(shù)人員可以清楚地了解到上述實(shí)施例方法可借助軟件加必需的通用硬件平臺(tái)的方式來實(shí)現(xiàn),當(dāng)然也可以通過硬件,但很多情況下前者是更佳的實(shí)施方式?;谶@樣的理解,本發(fā)明的技術(shù)方案本質(zhì)上或者說對(duì)現(xiàn)有技術(shù)做出貢獻(xiàn)的部分可以以軟件產(chǎn)品的形式體現(xiàn)出來,該計(jì)算機(jī)軟件產(chǎn)品存儲(chǔ)在一個(gè)存儲(chǔ)介質(zhì)(如ROM/RAM、磁碟、光盤)中,包括若干指令用以使得一臺(tái)終端設(shè)備(可以是手機(jī),計(jì)算機(jī),服務(wù)器,空調(diào)器,或者網(wǎng)絡(luò)設(shè)備等)執(zhí)行本發(fā)明各個(gè)實(shí)施例所述的方法。
上面結(jié)合附圖對(duì)本發(fā)明的實(shí)施例進(jìn)行了描述,但是本發(fā)明并不局限于上述的具體實(shí)施方式,上述的具體實(shí)施方式僅僅是示意性的,而不是限制性的,本領(lǐng)域的普通技術(shù)人員在本發(fā)明的啟示下,在不脫離本發(fā)明宗旨和權(quán)利要求所保護(hù)的范圍情況下,還可做出很多形式,這些均屬于本發(fā)明的保護(hù)之內(nèi)。