chapter21 Java多線程編程在Netty中的應用

chapter21 Java多線程編程在Netty中的應用

1. Java內存模型與多線程編程

1.1 Java內存模型

  • JVM規範定義了Java內存模型,來屏蔽各種操作系統、虛擬機實現廠商和硬件的內存訪問差異。
    1. 工作內存和主內存
      • 所有變量都存儲在主內存中,每個線程都有自己獨立的工作內存,它保存了該線程使用的變量的主內存的複製。線程間的變量訪問需要通過主內存來完成。
    2. Java內存交互協議
      • 定義了8種操作來完成主內存和工作內存的變量訪問
      • lock: 主內存變量,把一個變量標識爲某個線程獨佔的狀態。
      • unlock:主內存變量,把一個處於鎖定的變量釋放出來
      • read:主內存變量,把一個變量的值從主內存傳輸到線程的工作內存中,以便隨後的load操作使用
      • load:工作內存變量,把read讀取到的主內存中的變量值放入到工作內存的變量副本中
      • use:工作內存變量,把工作內存變量的值傳遞給java虛擬機執行引擎,每當虛擬機遇到一個需要使用到變量值的字節碼指令時,將會執行該操作
      • assign:工作內存變量,把從執行引擎接收到的變量的值賦給工作變量,每當虛擬機遇到一個變量賦值的字節碼指令時,將會執行該操作
      • store:工作內存變量,把工作內存中的一個變量的值傳送到主內存中,以便隨後的write操作使用
      • write:主內存變量,把store操作從工作內存中的變量值放入主內存的變量中
    3. Java的線程
      • 目前操作系統實現線程的方式主要有三種:【sun的jdk,在windows和linux上採用內核線程的實現方式】
      • 內核線程(KLT)實現:有內核來完成線程切換,並負責將線程任務映射到不同的處理器上
      • 用戶線程實現(UT):用戶線程是指完全建立在用戶空間線程庫上的線程,用戶線程的創建、啓動、運行、銷燬和切換完全在用戶態中完成,不需要內核幫助,因此性能更高
      • 混合實現:將內核線程和用戶線程混合在一起使用的方式

2、Netty的併發編程實線

2.1 對共享的可變數據進行正確同步

2.2 正確使用鎖

  • wait方法使線程等待某個條件,它必須在同步塊內部被調用,這個同步塊通常會鎖定當前對象實例。
  • 始終使用wait循環來調用wait方法,永遠不要在循環之外調用wait方法。
  • 喚醒線程,保守使用notifyAll,當處於等待的所有線程都在等待同一個條件,而每次只有一個線程可以從這個條件中被喚醒,那麼就用notify

2.3 volatile的正確使用

  • volatile時java提供的最輕量級的同步機制,Java內存模型對volatile專門定了一個特殊的訪問規則,僅僅解決了可見性的問題
  • 線程可見性
  • 禁止指令重排序優化
  • volatile最適合使用的是一個線程寫,其他線程讀的場合。

2.4 CAS指令和原子類

2.5 線程安全類的應用

  • 線程池
  • 併發集合
  • 新的同步器
  • 新的原子包裝類

2.6 讀寫鎖的應用

  • ReadWriteLock使用場景:
    1. 讀多寫少
    2. 讀寫鎖是可重入、可降級的,一個線程獲取讀寫鎖後,可以繼續遞歸獲取;從寫鎖可以降級爲讀鎖,以便快速釋放鎖資源
    3. ReentrantReadWriteLock支持獲取鎖的公平策略
    4. 讀寫鎖支持非阻塞的嘗試獲取鎖,如果獲取失敗,直接返回false,而不是阻塞
    5. 獲取鎖之後一定要釋放鎖,否則會發生鎖溢出異常。

2.7 線程安全性文檔說明

2.8 不要依賴線程優先級

  • Netty默認的線程工廠提供了實現類,開發了包含設置線程優先級字段的構造函數,這是個錯誤的決定。實際上JDK的優先級是無法跨平臺正確運行的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章