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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

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

3.1可見性

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

失效數(shù)據(jù)

非原子的64位操作

當(dāng)讀取一個(gè)非volatile類型的long變量時(shí),如果對(duì)該變量的讀操作和寫操作在不同的線程中執(zhí)行,那么很可能讀取到某個(gè)值的高32位和另外一個(gè)值的低32位

加鎖和可見性

加鎖的含義不僅互斥,還包括內(nèi)存可見性

volatile變量

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

滿足所有條件,才應(yīng)該使用volatile

  • 對(duì)變量的寫入不依賴變量的當(dāng)前值,只有單個(gè)線程更新變臉的值
  • 該變量不會(huì)與其他狀態(tài)一起納入不變形條件中
  • 在訪問時(shí)不需要加鎖

3.2發(fā)布與溢出

一般自定義類需要考慮發(fā)布(構(gòu)造方法), juc的類已經(jīng)處理過了

發(fā)布:是對(duì)象能夠在當(dāng)前作用域之外的代碼中使用

  • 將對(duì)象的引用存儲(chǔ)到公共靜態(tài)域。
  • 在非私有方法中返回引用。
  • 在發(fā)布某對(duì)象的時(shí)候可能會(huì)間接發(fā)布本不想發(fā)布的對(duì)象,如一個(gè)private的數(shù)組,一旦被發(fā)布,其中儲(chǔ)存的對(duì)象也會(huì)被發(fā)布

溢出:不應(yīng)該發(fā)布的被發(fā)布了

類對(duì)自己的內(nèi)部狀態(tài)進(jìn)行了同步操作,如果發(fā)布出去可能會(huì)破壞封裝性,并使程序難以維護(hù)不變性條件 一個(gè)對(duì)象在尚未準(zhǔn)備好就將它發(fā)布出去——溢出。

  • “內(nèi)部類發(fā)布也會(huì)引發(fā)溢出”,因?yàn)橹挥挟?dāng)對(duì)象通過構(gòu)造函數(shù)返回之后,才處于穩(wěn)定狀態(tài)。這種發(fā)布會(huì)導(dǎo)致this溢出。
  • “即使在構(gòu)造函數(shù)的最后一行發(fā)布也會(huì)有該問題”,指令重排序可能會(huì)引發(fā)一些奇怪的問題。而且該引用已經(jīng)不是null了,但是內(nèi)容還沒有初始化完畢也有可能。
  • “不要讓this在構(gòu)造期溢出!”

常見錯(cuò)誤

  • 1.在構(gòu)造函數(shù)中創(chuàng)建并啟動(dòng)線程 這個(gè)時(shí)候線程已經(jīng)獲得了this的引用(即使是隱式的,因?yàn)樵揜unnable或者Thread是所屬對(duì)象的內(nèi)部類),this引用幾乎總是被新線程所共享。 所以在構(gòu)造函數(shù)中創(chuàng)建線程沒有錯(cuò)誤,但是不要在構(gòu)造函數(shù)中啟動(dòng)它。
  • 2.注冊(cè)一個(gè)內(nèi)部類,使用this方法 可以使用靜態(tài)工廠和私有構(gòu)造函數(shù)來(lái)解決這個(gè)問題。

3.3線程封閉

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

特定的方法

例如在一個(gè)線程中進(jìn)行 讀取修改寫入,其他線程中進(jìn)行讀取

棧封閉

引用在局部變量中 注意不要讓當(dāng)前線程中的對(duì)象從所在線程溢出!

java的ThreadLocal

使用ThreadLocal可以做到線程隔離,每個(gè)線程都有自己?jiǎn)为?dú)的一個(gè)區(qū)域保存變量。

3.4不變性對(duì)象

  • 不可變對(duì)象滿足下列條件:
  • 所有域是final的,域內(nèi)部的域也是final的
  • 所有域不可改變
  • this沒有在構(gòu)造的時(shí)候逸出

final域

使用volatile類型來(lái)發(fā)布不可變對(duì)象

3.5安全發(fā)布

不正確的發(fā)布:正確的對(duì)象被破壞

導(dǎo)致其他縣城看到尚未創(chuàng)建完的對(duì)象

不可變對(duì)象與初始化安全

安全發(fā)布的常用模式

  • 在靜態(tài)初始化對(duì)象引用,因?yàn)镴VM的類加載過程中是同步的
  • 對(duì)對(duì)象引用使用volatile或AtomicReference
  • 將對(duì)象引用放入final域中
  • 對(duì)對(duì)象引用加鎖
  • 案例:

    • 將一個(gè)鍵值對(duì)放入HashTable,syhronizedMap或者ConcurrentMap中
    • 靜態(tài)構(gòu)造的對(duì)象 public static Holder holder= new Holder(42)

    事實(shí)不可變對(duì)象

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

    可變對(duì)象

    • 不僅要保證發(fā)布時(shí)的狀態(tài)可見性
    • 每次訪問時(shí)同樣需要使用同步來(lái)確保后需修改操作的可見性

    小結(jié)

    • 不可變對(duì)象可以通過任意機(jī)制來(lái)發(fā)布()
    • 事實(shí)不可變對(duì)象必須通過安全方式來(lái)發(fā)布
    • 可變對(duì)象必須通過安全方式來(lái)發(fā)布,并且是線程安全的或者由某個(gè)所保護(hù)起來(lái)

    安全的共享對(duì)象

    在發(fā)布一個(gè)對(duì)象的時(shí)候需要明確指出該對(duì)象的多線程共享規(guī)則:

  • 是線程封閉?:只能由一個(gè)線程擁有
  • 是只讀共享?:只能并發(fā)讀
  • 是線程安全共享?:類內(nèi)部實(shí)現(xiàn)了同步,可以隨意使用
  • 是保護(hù)對(duì)象?:類內(nèi)部沒有實(shí)現(xiàn)同步,需要使用者在外部同步 原文地址: www.victor123.cn/2018/04/15/…
  • 轉(zhuǎn)載于:https://juejin.im/post/5ad2a0a45188257ddb100f27

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。