張欽顧仰 鄧 迪 王 宇
(上海航天電子技術(shù)研究所,上海 200109)
近年來,智能終端設(shè)備取得了突飛猛進的發(fā)展,Android(以下稱安卓)系統(tǒng)可謂是頭號功臣,居功甚偉。2007年11月5日,谷歌公司首次向外界介紹了安卓系統(tǒng),使得安卓系統(tǒng)可以進入大家的視野。它基于Linux系統(tǒng)開發(fā),主要用于智能終端設(shè)備,例如平板電腦和智能手機。由于其完全開源,導(dǎo)致其傳播非常快,迅速占領(lǐng)了一半以上的市場占有率,成為當(dāng)下最主流的智能終端設(shè)備操作系統(tǒng)。
隨著導(dǎo)彈遙測系統(tǒng)的通用化、小型化要求越來越高,基于ARM的平板電腦硬件平臺成為了新的選項之一。相較于過去的地面測試設(shè)備和筆記本的組合,手持平板設(shè)備有以下優(yōu)點:
(1)體積小,便于攜帶,適應(yīng)復(fù)雜多變的作戰(zhàn)環(huán)境;(2)成本低,更換方便,提供更好的后勤保障選擇;(3)智能一體化,具有更高的保密性和可靠性。
然而手持平板設(shè)備相比傳統(tǒng)筆記本也有一些不足,比如CPU等核心器件的性能沒有筆記本強大,所以為了達到使用要求必須同時使用多核CPU并行處理數(shù)據(jù)。這就面臨了Java開發(fā)中經(jīng)常出現(xiàn)的高并發(fā)問題。為了解決單線程轉(zhuǎn)多線程帶來的高并發(fā)問題,讀寫鎖是一個很好的選擇。
與傳統(tǒng)順序執(zhí)行程序相比,Java并發(fā)程序中多線程的線程安全一直是困擾廣大設(shè)計師的難題。通常Java在處理數(shù)據(jù)時都會把變量存在主內(nèi)存,使用變量時都是把變量拷貝到自己的工作空間進行使用,待使用完后重新賦值回主內(nèi)存。
圖1 Java內(nèi)存訪問
但是如果是多核系統(tǒng)架構(gòu),就會產(chǎn)生風(fēng)險。因為每個CPU核都擁有獨立的運算控制器,如果他們同時把同一個變量拷貝到線程內(nèi)存進行計算,那么計算完成時,后一個線程的回歸值會覆蓋前一個線程的回歸值,造成共享變量不可見,導(dǎo)致出現(xiàn)臟數(shù)據(jù)和不可預(yù)期的結(jié)果。
圖2 多線程導(dǎo)致的共享變量不可見
當(dāng)一個線程讀取內(nèi)存時同步鎖會給該內(nèi)存加鎖,直到訪問完畢之后釋放鎖。其他線程如果想要訪問,就會發(fā)現(xiàn)內(nèi)存被鎖上,導(dǎo)致線程被堵塞。這樣做可以保證同時只有一個線程訪問,以此確保數(shù)據(jù)唯一性。
圖3 Synchronized獨占鎖
同步獨占鎖在保證數(shù)據(jù)唯一的情況下,會導(dǎo)致其他沒有獲取內(nèi)部鎖的線程堵塞。如果程序?qū)懭雰?nèi)存次數(shù)占比遠遠高于內(nèi)存讀取次數(shù),使用同步鎖可以有效規(guī)避高并發(fā);但是一旦程序讀取內(nèi)存次數(shù)占比遠遠高于內(nèi)存寫入次數(shù)時,線程堵塞會大大影響性能。使用讀寫鎖可以有效解決這個問題。當(dāng)運用讀寫鎖時,寫入加鎖,其他線程不能讀取和寫入,但是讀取加鎖時,其他線程只是不能寫入,不影響讀取操作,所以讀寫鎖本質(zhì)上是一種可重入鎖。
由于遙測主要用于接收數(shù)據(jù),導(dǎo)致其程序主要讀取數(shù)據(jù),僅僅在判斷數(shù)據(jù)是否正確時需要寫入數(shù)據(jù)。而讀取操作并沒有必要使用同步鎖,所以讀寫鎖更適合。
圖4 Reentrant Read Write Lock結(jié)構(gòu)
通過讀寫鎖的方法,對讀取和寫入分別設(shè)置一個內(nèi)部鎖,大部分時間讀取鎖都解鎖,只在寫入時加鎖。并且加入了一個狀態(tài)機記錄其他的上鎖狀態(tài)的對應(yīng)情況。
public Reentrant Read Write Lock(boolean fair){
sync=fair?new Fair Sync():new Non fair Sync();
reader Lock=new Read Lock(this);
writer Lock=new Write Lock(this);
}
/**Possible state transitions:
*NEW->COMPLETED->RECEIVE正常的上鎖狀態(tài)
*NEW->COMPLETED->LAUNCH其他的上鎖狀態(tài)
*NEW->STOP停止
*NEW->EXIT關(guān)閉
*NEW->INTERRUPTING->INTERRUPTED中斷
*/
private volatile int state;
private static final int RECEIVE=1;
private static final int LAUNCH=2;
private static final int INTERRUPTING=3;
private static final int STOP=4;
private static final int INTERRUPTED=5;
private static final int COMPLETED=6;
private static final int EXIT=7;
當(dāng)遙測接收數(shù)據(jù)時,只讀取不寫入,狀態(tài)機state=1;當(dāng)接收一段數(shù)據(jù)進行數(shù)據(jù)比對時,開啟寫入鎖,狀態(tài)機state=2。由于遙測接收寫入的數(shù)據(jù)不依賴于當(dāng)前值,所以可以用volatile替代Synchronized,不僅不會影響線程調(diào)度,還能解決重排序問題。
通過分析讀取和寫入的高低權(quán)重,將權(quán)重排序并分別加鎖和解鎖,做到優(yōu)先處理高權(quán)重請求,優(yōu)化處理流程的同時保證數(shù)據(jù)的唯一,并且在出現(xiàn)異常的時候提供中斷功能,確保遙測監(jiān)控的安全。
本文在同步鎖的基礎(chǔ)上,討論了運用讀寫鎖原理解決ARM芯片多線程高并發(fā)的問題,為導(dǎo)彈遙測接收端移植平臺實現(xiàn)小型化提供新的思路和新的方法,為將來的導(dǎo)彈適應(yīng)多環(huán)境高機動作戰(zhàn)提供可行性。
[1]鄭逸凡.高并發(fā)網(wǎng)站的前端優(yōu)化技術(shù)研究[J].通化師范學(xué)院學(xué)報,2015(08):12-14.
[2]陳涵生.Java語言與Java技術(shù)[J].計算機工程,1997(04):3-6.
[3]丁衛(wèi)峰.亦步亦趨的代碼移植——從Linux到Windows的代碼移植[J].程序員:CSDN開發(fā)高手,2004(2):93-96.
[4]吉建平.選取我國代碼制圖文電視糾錯碼的幾點考慮[J].廣播與電視技術(shù),1988(03):26-31,35.