Java併發編程(-)基礎

多線程一定快嗎

由於線程有創建和上下文切換的開銷,短時間的操作會比單線程更慢

如何減少上下文切換

  • 無鎖併發編程:多線程競爭鎖,會引發上下文切換,所以可以減少鎖的使用,如,按照數據的ID按照Hash取模分段,不同的線程處理不同的段
  • CAS算法:Java的Atomic包使用這個來更新數據,不需要加鎖
  • 使用最少線程:避免創建不需要的線程
  • 協程:單線程中實現多任務調度,在單線程中維持多任務間的切換

volatile

他在多處理器開發中保證了共享變量的“可見性”,可見性指當一個線程修改一個共享變量時,另外一個線程能讀到這個修改的值。

爲了提高處理速度,處理器不直接和內存進行通信,而是先將系統內存的數據讀到內部緩存後進行操作,但操作完成不知道何時回寫會內存,所以普通的操作會出現兩個處理器的數據不一致的情況,而導致多線程數據不統一,這時候可以使用volatile。
volatile會做兩件事情:

  1. 將當前處理器緩存的數據寫回到系統內存中
  2. 這個寫回內存的操作會使其他CPU裏緩存了該內存地址的數據無效

synchronized

Java中的內一個對象都可以作爲鎖,

  • 對於普通同步方法,鎖是當前實例對象
  • 對於靜態同步方法,鎖是當前類的Class對象
  • 對於同步方法塊,鎖是Synchronized括號裏的對象

synchronized在JVM的實現原理,JVM進入和退出Monitor對象來實現方法同步和代碼塊的同步,包括monitorenter和monitorexit,在編譯後插入的同步代碼塊的開始和結束或者異常的位置,JVM保證這兩個是成對出現,當且一個monitor被持有後就鎖定。
synchronized的鎖是存在java對象頭裏的

原子操作

  • 總線鎖
    兩個處理器同時從各自的緩存中讀取變量i,分別進行加1,然後寫回系統內存,可能會出現覆蓋寫入的情況,結果不是3,而是2
    處理器使用總線鎖可以處理:提供一個LOCK信號,當一個處理器在總線上輸出此信號時,其他處理器的請求被阻塞,處理器可以獨佔共享內存。
    總線鎖,鎖住了所有的內存通信,開銷太大。
  • 緩存鎖
    內存區域如果被緩存在處理器緩存中,並且Lock操作期間被鎖定,當他執行鎖操作回寫到內存是,處理器不在總線上聲明lock,而是修改內部的內存地址,並允許他的緩存一致性機制來保證原子性。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章