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