日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java并发编程实战-第三章-对象的共享

發布時間:2023/12/19 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java并发编程实战-第三章-对象的共享 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

3.1可見性

  • 首先我們需要知道的是,java的線程都有自己獨立的緩存,線程之間進行共享變量的交互是通過自身和緩存和主存的交互實現的。
  • 如果線程的每次更改緩存都刷入主存,主存每次被一個線程的緩存修改,都通知所有的線程刷新自身的緩存的話,那樣就太不經濟了。
  • 由于1和2,就會產生一個現象:當線程1修改了一個共享變量之后,線程2獲取的共享變量還是更改前的值。即線程1更改共享變量并沒有刷入主存,或者線程2并沒有去主存中獲取到新的共享變量,或以上兩者皆有
  • 為了解決內存可見性我們可以使用volatile關鍵字和同步這兩種方式
  • 變量的讀取,指令重排序

失效數據

非原子的64位操作

當讀取一個非volatile類型的long變量時,如果對該變量的讀操作和寫操作在不同的線程中執行,那么很可能讀取到某個值的高32位和另外一個值的低32位

加鎖和可見性

加鎖的含義不僅互斥,還包括內存可見性

volatile變量

  • 用來確保變量的更新操作通知到其他線程
  • 編譯器與運行時都會注意到這個變量時共享的,不會進行重排序
  • volatile不會被緩存在寄存器或者其他處理器不可見的地方,讀取變量時,總能返回最新的寫入值

滿足所有條件,才應該使用volatile

  • 對變量的寫入不依賴變量的當前值,只有單個線程更新變臉的值
  • 該變量不會與其他狀態一起納入不變形條件中
  • 在訪問時不需要加鎖

3.2發布與溢出

一般自定義類需要考慮發布(構造方法), juc的類已經處理過了

發布:是對象能夠在當前作用域之外的代碼中使用

  • 將對象的引用存儲到公共靜態域。
  • 在非私有方法中返回引用。
  • 在發布某對象的時候可能會間接發布本不想發布的對象,如一個private的數組,一旦被發布,其中儲存的對象也會被發布

溢出:不應該發布的被發布了

類對自己的內部狀態進行了同步操作,如果發布出去可能會破壞封裝性,并使程序難以維護不變性條件 一個對象在尚未準備好就將它發布出去——溢出。

  • “內部類發布也會引發溢出”,因為只有當對象通過構造函數返回之后,才處于穩定狀態。這種發布會導致this溢出。
  • “即使在構造函數的最后一行發布也會有該問題”,指令重排序可能會引發一些奇怪的問題。而且該引用已經不是null了,但是內容還沒有初始化完畢也有可能。
  • “不要讓this在構造期溢出!”

常見錯誤

  • 1.在構造函數中創建并啟動線程 這個時候線程已經獲得了this的引用(即使是隱式的,因為該Runnable或者Thread是所屬對象的內部類),this引用幾乎總是被新線程所共享。 所以在構造函數中創建線程沒有錯誤,但是不要在構造函數中啟動它。
  • 2.注冊一個內部類,使用this方法 可以使用靜態工廠和私有構造函數來解決這個問題。

3.3線程封閉

數據僅在單線程中被訪問,即數據不共享。 幾種方式:

特定的方法

例如在一個線程中進行 讀取修改寫入,其他線程中進行讀取

棧封閉

引用在局部變量中 注意不要讓當前線程中的對象從所在線程溢出!

java的ThreadLocal

使用ThreadLocal可以做到線程隔離,每個線程都有自己單獨的一個區域保存變量。

3.4不變性對象

  • 不可變對象滿足下列條件:
  • 所有域是final的,域內部的域也是final的
  • 所有域不可改變
  • this沒有在構造的時候逸出

final域

使用volatile類型來發布不可變對象

3.5安全發布

不正確的發布:正確的對象被破壞

導致其他縣城看到尚未創建完的對象

不可變對象與初始化安全

安全發布的常用模式

  • 在靜態初始化對象引用,因為JVM的類加載過程中是同步的
  • 對對象引用使用volatile或AtomicReference
  • 將對象引用放入final域中
  • 對對象引用加鎖
  • 案例:

    • 將一個鍵值對放入HashTable,syhronizedMap或者ConcurrentMap中
    • 靜態構造的對象 public static Holder holder= new Holder(42)

    事實不可變對象

    程序不會去修改,例如Date雖然是可變的,但是放入了同步的HashMap中,且不會修改,那么就認為是不可變的對象

    可變對象

    • 不僅要保證發布時的狀態可見性
    • 每次訪問時同樣需要使用同步來確保后需修改操作的可見性

    小結

    • 不可變對象可以通過任意機制來發布()
    • 事實不可變對象必須通過安全方式來發布
    • 可變對象必須通過安全方式來發布,并且是線程安全的或者由某個所保護起來

    安全的共享對象

    在發布一個對象的時候需要明確指出該對象的多線程共享規則:

  • 是線程封閉?:只能由一個線程擁有
  • 是只讀共享?:只能并發讀
  • 是線程安全共享?:類內部實現了同步,可以隨意使用
  • 是保護對象?:類內部沒有實現同步,需要使用者在外部同步 原文地址: www.victor123.cn/2018/04/15/…
  • 轉載于:https://juejin.im/post/5ad2a0a45188257ddb100f27

    總結

    以上是生活随笔為你收集整理的java并发编程实战-第三章-对象的共享的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。