可以使用JDK提供的Exchager類進行同步交換:進行資料交換的雙方將互相等待對方,直到雙方的資料都準備完畢,才進行交換。Exchager類很少用到,但理解資料交換的時機卻十分重要,這是一個基於trade-off的系統設計。下述分析方法能擴充套件到諸多系統設計的場景中,幫助我們更好的進行trade-off。
《Java併發程式設計實戰》中介紹了判定資料交換時機的兩種方案,卻不甚清晰。從“時機選擇的目的”出發,實際上存在著三種方案,各方案又有優劣,從而產生了trade-off。本文比較了這三種方案,通過對資料交換時機的分析加強trade-off的意識。
定義
資料交換:在Exchanger的兩方柵欄機制中,雙方互相等待對方的資料。
如讀執行緒在讀取發生前持有“空快取”,寫執行緒在寫入完成後持有“滿緩衝”(“滿”只表示寫入完成),那麼資料交換就是指將讀執行緒的“空緩衝”與寫執行緒的“滿緩衝”交換。
方案比較
依據“時機選擇的的目的”,存在三種方案:
方案1. 交換次數最少
從交換次數最少的目的出發,交換行為應該發生在緩衝滿和緩衝空時,這兩種情況下都不得不發生交換,以滿足最低的響應需求。
緩衝滿時(填充執行緒的緩衝),填充任務發現無法繼續填充緩衝區,就發起交換,以減少資料(到空)繼續填充;緩衝空時(清空執行緒的緩衝),清空任務發現無法繼續清空,就發起交換,以增加資料(到滿)繼續清空。
也可以將實際的交換任務委派給專門的交換執行緒,填充任務和清空任務都向該執行緒申請執行交換。
方案2. 交換最及時(響應最及時)
從響應最及時的目的出發,交換行為應該發生在緩衝剛增加資料和緩衝剛減少資料時,以滿足“存在資料即交換”的最高的響應需求。
這種方案相當於去掉了緩衝區。一方面,一旦快取不空就立刻發生交換,交換後就沒有了資料;另一方面,一旦快取空就開始交換資料,交換後快取就不空。看起來資料根本需要寫入快取就完成了交換。
也可以設定一個特別小的緩衝,比如1個位元組。但交換區的緩衝減小,只會讓交換雙方各自維護的緩衝區加大。
方案3. 適度的交換頻率和響應
很明顯:交換次數最少的話,一些資料的處理過程就將延遲;響應最及時的話,交換頻率太高,很浪費效能,甚至大型系統中耗電都會成為問題。
所以可採用折中的方案,達到適度的交換頻率和響應:交換行為發生在緩衝被填充到一定程度並保持一定時間 t 後,同時一旦緩衝滿或緩衝空就立即發生交換。
如果將時間 t 設定為 0,則退化為方案2;如果將時間 t 設定無窮大,則退化為方案1,從而既能相容以上兩種方案,又能根據實際響應需求靜態配置,甚至根據實時的效能分析結果進行動態調整。
如果將Exchager比作“資料交換系統”,方案3即完成了對“資料交換系統”的trade-off,也就是基於成本(如耗電等)、收益(如延遲等)對系統設計作出的權衡、妥協。
總結
通過對三種Exchager資料交換時機的分析,加強了我們在系統設計中的trade-off意識。
《Java併發程式設計實戰》中介紹了方案1和方案3。直接在書中看到方案1和方案3可能很難理解,但分析了上述trade-off過程後,就能輕鬆理解資料交換的時機了。
本文連結:從Exchager資料交換到基於trade-off的系統設計
作者:猴子007
出處:monkeysayhi.github.io
本文基於 知識共享署名-相同方式共享 4.0 國際許可協議釋出,歡迎轉載,演繹或用於商業目的,但是必須保留本文的署名及連結。