代碼整潔_併發編程

對象是過程的抽象,線程是調度的抽象。
編寫整潔的併發程序很難


1. 爲什麼要併發

併發是一種解耦策略。幫助我們把做什麼(目的)和何時(時機)做分
解開。 解耦目的與時機能明顯地改善應用程序的吞吐量和結構。
併發:
併發會在性能和編寫額外代碼上添加一些開銷
正確的併發是複雜的,即便對於簡單的問題也是如此。
併發缺陷並非總能重現
併發常常需要對設計策略的根本性修改

2 併發防禦原則:

  • 2.1 單一權責原則(SRP):
    方法/類/組件應當只有一個修改的理由
    併發設計自身足夠複雜到成爲修改的理由,所以也該從其他代碼中分離出來。
    考慮問題:
    併發相關代碼有自己的開發、修改和調優生命週期
    開發相關代碼有自己要對付的挑戰,和非併發相關代碼不同,會更困難
    沒有外在影響,寫的不好的併發代碼出錯也會很多。
    建議:
    分離併發相關代碼與其他代碼。
  • 2.2 限制數據作用域
    採用synchronized關鍵字在代碼中保護一塊使用共享對象的臨界區
  • 2.3 使用數據複本
    避免共享數據的好方法之一避免共享數據。 只讀方式創建複本,然後收集複本合併。
  • 2.4 線程應儘可能地獨立
    建議:
    嘗試將數據分解到可被獨立線程(可能在不同處理器上)操作的獨立子集。

3 使用java 線程庫。

使用executor框架執行無關任務。 儘可能使用非鎖定解決方案
建議:
檢讀可用的類: 對於Java,掌握java.util.concurrent、 java.util.concurrent.atomic、 java.util.concurrent.locks,
ReentrantLock     可在一個方法中獲取、在另一個方法中釋放的鎖
Semaphore     經典的“信號”的一種實現,有計數器的鎖
CountDownLatch    在釋放所有等待的線程之前,等待指定數量事件發生的鎖,這樣,所有線程都平等地幾乎同時啓動。

4 瞭解執行模型

基礎定義:
限定資源, 互斥, 線程飢餓, 死鎖, 活鎖
執行模型:
生產者-消費者模型 (之間的隊列就是一種限定資源)
讀者-作者模型 宴席哲學家
如何找到必須鎖定的代碼區域並鎖定

5 警惕同步方法之間的依賴

避免使用一個共享對象的多個方法。但有時必須使用一個共享代碼的多個方法,有三種寫對代碼的手段:
- 基於客戶端的鎖定
客戶端代碼在調用第一個方法前鎖定服務器,確保鎖的範圍覆蓋了調用使用最後一個方法的代碼
- 基於服務端的鎖定
在服務器內創建鎖定服務器端的方法,調用所有方法,然後解鎖。讓客戶端調用新方法。
- 適配服務端
創建執行鎖定的中間層。這是一種基於服務器的鎖定的例子,但不修改原始服務端代碼。

6. 保持同步區域微小

7. 儘早考慮關閉問題,儘早令其工作正常。

8. 測試線程代碼。

建議:
不要將系統錯誤歸咎於偶發事件
不要同時追蹤非線程缺陷和線程缺陷。確保代碼在線程之外可工作。
編寫可拔插的線程代碼,這樣就能在不同配置環境下運行
儘早並經常地在所有目標平臺上運行程序代碼
兩種裝置代碼的方式: 硬編碼 , 自動化(使用Aspect-Oriented Framework, CGLIB, ASM等工具來編程來裝置代碼)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章