成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

「Java并發(fā)編程實(shí)戰(zhàn)」之對(duì)象的共享

phodal / 3441人閱讀

摘要:當(dāng)某個(gè)不應(yīng)該發(fā)布的對(duì)象被發(fā)布時(shí),這種情況被稱為逸出。線程安全共享線程安全的對(duì)象在其內(nèi)部實(shí)現(xiàn)同步,因此多線程可以通過對(duì)象的公有接口來進(jìn)行訪問而不需要進(jìn)一步的同步。

前言

  本系列博客是對(duì)《Java并發(fā)編程實(shí)戰(zhàn)》的一點(diǎn)總結(jié),本篇主要講解以下幾個(gè)內(nèi)容,內(nèi)容會(huì)比較枯燥??赡艽蠹铱礃?biāo)題不能能直觀的感受出到底什么意思,這就是專業(yè)術(shù)語,哈哈,解釋下,術(shù)語(terminology)是在特定學(xué)科領(lǐng)域用來表示概念的稱謂的集合,在我國(guó)又稱為名詞或科技名詞(不同于語法學(xué)中的名詞)。術(shù)語是通過語音或文字來表達(dá)或限定科學(xué)概念的約定性語言符號(hào),是思想和認(rèn)識(shí)交流的工具。我就用白話文來給大家解釋下這些術(shù)語。

線程安全

  什么是線程安全?這算是老生常談的問題了,相信大家在面試的過程中也遇到過,在線程安全的定義中,最核心的概念就是正確性,如果對(duì)線程安全性的定義是模糊的,那么就是缺乏對(duì)正確性的清晰定義。正確性的含義是,某個(gè)類的行為與其規(guī)范完全一致,在良好的規(guī)范中通常會(huì)定義各種不變性條件來約束對(duì)象的狀態(tài),以及定義各種后驗(yàn)條件來描述對(duì)象操作的結(jié)果。說白了就是一個(gè)類無論是在單線程環(huán)境還是多線程環(huán)境中都能正確的執(zhí)行,那么這個(gè)類就是線程安全的。如果在線程交替執(zhí)行的過程中導(dǎo)致不可預(yù)料的結(jié)果,那么就是線程不安全的。

可見性

  假如有一個(gè)變量,現(xiàn)在對(duì)它進(jìn)行讀寫操作,可見性說的就是當(dāng)前線程對(duì)變量的寫操作是否對(duì)其它線程可見,就是其它線程能不能知道你對(duì)這個(gè)變量做了修改。如果不能保證可見,必須使用同步機(jī)制。否則當(dāng)其他線程來讀這個(gè)變量的時(shí)候,可能會(huì)得到一個(gè)已經(jīng)失效的值。這個(gè)值就被稱為失效數(shù)據(jù)。
  
  在這里提醒大家,對(duì)于非volatile類型的long和double變量JVM允許將64位的讀操作或?qū)懖僮鞣纸鉃閮蓚€(gè)32位的操作,當(dāng)讀一個(gè)非volatile類型的long變量時(shí),如果讀寫操作是在不同的線程中執(zhí)行,那么很可能會(huì)讀取到某個(gè)值的高32位和另一個(gè)值的低32位,所以在多線程環(huán)境中使用共享可變的long和double等類型的變量時(shí)不安全的,除非使用關(guān)鍵字volatile來聲明它們,或者用鎖保護(hù)起來。
1.現(xiàn)在來介紹一下Volatile:
Java語言提供了一種稍弱的同步機(jī)制,即volatile類型,用來確保將變量的更新操作通知到其他線程。使用就是在變量前面加上volatile即可。在 JMM 中,線程之間的通信采用共享內(nèi)存來實(shí)現(xiàn)的。volatile 的內(nèi)存語義是:

當(dāng)寫一個(gè) volatile 變量時(shí),JMM 會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存中的共享變量值,立即刷新到主內(nèi)存中。

當(dāng)讀一個(gè) volatile 變量時(shí),JMM 會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存設(shè)置為無效,直接從主內(nèi)存中讀取共享變量。

2.volatile的使用條件:

對(duì)變量的寫入操作不依賴變量的當(dāng)前值,或者你能確保只有單個(gè)線程更新變量的值。

該變量不會(huì)與其他狀態(tài)變量一起納入不變性條件中。

在訪問變量時(shí)不需要加鎖。

加鎖機(jī)制既可以確??梢娦杂挚梢源_保原子性,而volatile變量只能確??梢娦?,千萬不要用它來確保原子性操作。

發(fā)布與逸出

發(fā)布一個(gè)對(duì)象的意思就是使對(duì)象能夠在當(dāng)前作用域之外的代碼中使用,例如,將一個(gè)指向該對(duì)象的的引用保存到其他代碼可以訪問的地方,或者在某一個(gè)非私有的方法中返回該引用,或者將引用傳遞到其他類方法中。當(dāng)某個(gè)不應(yīng)該發(fā)布的對(duì)象被發(fā)布時(shí),這種情況被稱為逸出。

線程封閉

當(dāng)訪問共享的可變數(shù)據(jù)時(shí),通常需要使用同步。一種避免使用同步的方式就是不同享數(shù)據(jù),如果僅在單線程內(nèi)訪問數(shù)據(jù),就不需要同步,這種技術(shù)被稱為線程封閉,它是實(shí)現(xiàn)線程安全性最簡(jiǎn)單的方法之一。下面介紹幾種線程封閉技術(shù)。
1.Ad-hoc線程封閉
Ad-hoc線程封閉是指,維護(hù)線程封閉性的職責(zé)完全有程序?qū)崿F(xiàn)來承擔(dān)。例如可見性修飾符或局部變量,能將對(duì)象封閉到目標(biāo)線程上。事實(shí)上對(duì)于線程封閉對(duì)象通常保存在共有變量中。Ad-hoc線程封閉是非常脆弱的,所以程序中盡量少使用它,可以使用以下兩種技術(shù)(棧封閉,ThreadLocal)。
2.棧封閉
棧封閉也被成為線程內(nèi)部使用或者線程局部使用,不要與ThredaLocal混淆,比Ad-hoc更易于維護(hù),也更加健壯。在棧封閉中,只能通過局部變量才能訪問對(duì)象。

//偽代碼
public void test(){
//定義一個(gè)變量
Set set ;
// 實(shí)例化一個(gè)TreeSet對(duì)象,并將該對(duì)象的一個(gè)引用保存到set中。
set = new TreeSet();
}

這樣TreeSet對(duì)象就被封閉在局部變量中,因此也被封閉到執(zhí)行線程中,它位于執(zhí)行線程的棧中,其他線程無法訪問這個(gè)棧。
3.ThreadLocal
維持線程封閉性的一種更為規(guī)范的方法是使用ThreadLocal,這個(gè)類能使線程中的某個(gè)值與保存值的對(duì)像關(guān)聯(lián)起來,ThreadLocal提供了get與set等訪問接口或方法,這些方法為每個(gè)使用該變量的線程都存有一份獨(dú)立的副本,因此get總是返回由當(dāng)前線程執(zhí)行set時(shí)設(shè)置的最新值。ThreadLocal通常用于防止對(duì)可變對(duì)像的單實(shí)例變量或全局變量進(jìn)行共享。

   //保存一個(gè)數(shù)據(jù)庫(kù)連接對(duì)像
   public static ThreadLocal connectionThreadLocal = 
   new ThreadLocal(){
       @Override
       protected Connection initialValue() {
           return DriverManager.getConnection(DB_URl);
       }
   };
   //每個(gè)線程使用時(shí)直接get
   public static Connection getConnection(){
       return connectionThreadLocal.get();
   }
不變性

如果某個(gè)對(duì)像在被創(chuàng)建之后其狀態(tài)就不能被修改,那么這個(gè)對(duì)象就是不可變對(duì)象,線程安全性是是不可變對(duì)象的固有屬性之一。當(dāng)滿足一下條件時(shí),對(duì)象才是不可變的:

對(duì)象創(chuàng)建后其狀態(tài)就不能修改。

對(duì)象的所有域都是final類型。

對(duì)象是正確創(chuàng)建的(在對(duì)象的創(chuàng)建期間,this引用沒有逸出)

Final域:
用于構(gòu)造不可變對(duì)象。final類型的域是不能修改的(但如果final域所引用的對(duì)象是可變的,那么這些引用的對(duì)象是可以修改的)。然而在java內(nèi)存模型中,final域還有著特殊的語義。final域能確保初始化過程的安全性,從而可以不受限制的訪問不可變對(duì)象,并在共享這些對(duì)象時(shí)無須同步。

安全發(fā)布

1.要安全發(fā)布一個(gè)對(duì)象,對(duì)象的引用以及對(duì)象的狀態(tài)必須同時(shí)對(duì)其他線程可見,一個(gè)正確構(gòu)造的對(duì)象可以通過以下方式來安全的發(fā)布:

在靜態(tài)初始化函數(shù)中初始化一個(gè)對(duì)象引用。

將對(duì)象的引用保存到volatile類型的域或者Atomicreferance對(duì)象中。

將對(duì)象的引用保存到某個(gè)正確構(gòu)造對(duì)象的final類型域中。

將對(duì)象的引用保存到一個(gè)由鎖保護(hù)的域中。

2.在并發(fā)程序中使用和共享對(duì)象時(shí),可以使用一些實(shí)用的策略:

線程封閉:線程封閉的對(duì)象只能由一個(gè)線程擁有,對(duì)象被封閉在該線程中,并且只能由這個(gè)線程修改

只讀共享:在沒有額外同步的情況下,共享的只讀對(duì)象可以由多個(gè)線程并發(fā)訪問,但任何線程都不能修改它,共享的只讀對(duì)象包括不可變對(duì)象和事實(shí)不可變對(duì)象。

線程安全共享:線程安全的對(duì)象在其內(nèi)部實(shí)現(xiàn)同步,因此多線程可以通過對(duì)象的公有接口來進(jìn)行訪問而不需要進(jìn)一步的同步。

保護(hù)對(duì)象:被保護(hù)的對(duì)象只能通過持有特定的鎖來訪問,保護(hù)對(duì)象包括封裝在其他線程安全對(duì)象中的對(duì)象,以及已發(fā)布的并且由某個(gè)特定鎖保護(hù)的對(duì)象。

大家看后辛苦點(diǎn)個(gè)贊點(diǎn)個(gè)關(guān)注哦!查看個(gè)人主頁,有更多的博客哦。如有錯(cuò)誤,煩請(qǐng)指正。
有興趣加群一起交流。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76276.html

相關(guān)文章

  • Java并發(fā)編程實(shí)戰(zhàn)》讀書筆記-第1章 簡(jiǎn)介

    摘要:線程允許同一個(gè)進(jìn)程中同時(shí)存在多個(gè)程序控制流。線程也被稱為輕量級(jí)進(jìn)程?,F(xiàn)代操作系統(tǒng)中,都是以線程為基本的調(diào)度單位,而不是進(jìn)程。 并發(fā)簡(jiǎn)史 在早期的計(jì)算機(jī)中不包含操作系統(tǒng),從頭至尾都只執(zhí)行一個(gè)程序,并且這個(gè)程序能訪問計(jì)算機(jī)所有資源。操作系統(tǒng)的出現(xiàn)使得計(jì)算機(jī)每次能運(yùn)行多個(gè)程序,并且不同的程序都在單獨(dú)的進(jìn)程中運(yùn)行:操作系統(tǒng)為各個(gè)獨(dú)立執(zhí)行的進(jìn)程分配內(nèi)存、文件句柄、安全證書等。不同進(jìn)程之間通過一些...

    zhoutk 評(píng)論0 收藏0
  • java并發(fā)編程實(shí)戰(zhàn)6】AQS獨(dú)占鎖ReentrantLock實(shí)現(xiàn)

    摘要:鎖與很好的隔離使用者與實(shí)現(xiàn)者所需要關(guān)注的領(lǐng)域。那么這個(gè)就是包裝線程并且放入到隊(duì)列的過程實(shí)現(xiàn)的方法。也證實(shí)了就是獲取鎖的線程的節(jié)點(diǎn)。如果發(fā)生異常取消請(qǐng)求,也就是將當(dāng)前節(jié)點(diǎn)重隊(duì)列中移除。 前言 自從JDK1.5后,jdk新增一個(gè)并發(fā)工具包java.util.concurrent,提供了一系列的并發(fā)工具類。而今天我們需要學(xué)習(xí)的是java.util.concurrent.lock也就是它下面的...

    sixleaves 評(píng)論0 收藏0
  • Java 并發(fā)編程系列帶你了解多線程

    摘要:的內(nèi)置鎖是一種互斥鎖,意味著最多只有一個(gè)線程能持有這種鎖。使用方式如下使用顯示鎖之前,解決多線程共享對(duì)象訪問的機(jī)制只有和。后面會(huì)陸續(xù)的補(bǔ)充并發(fā)編程系列的文章。 早期的計(jì)算機(jī)不包含操作系統(tǒng),它們從頭到尾執(zhí)行一個(gè)程序,這個(gè)程序可以訪問計(jì)算機(jī)中的所有資源。在這種情況下,每次都只能運(yùn)行一個(gè)程序,對(duì)于昂貴的計(jì)算機(jī)資源來說是一種嚴(yán)重的浪費(fèi)。 操作系統(tǒng)出現(xiàn)后,計(jì)算機(jī)可以運(yùn)行多個(gè)程序,不同的程序在單獨(dú)...

    Elle 評(píng)論0 收藏0
  • <java并發(fā)編程實(shí)戰(zhàn)>學(xué)習(xí)三

    摘要:線程封閉當(dāng)訪問共享的可變數(shù)據(jù)時(shí),通常需要使用同步。如果僅在單線程內(nèi)訪問數(shù)據(jù),就不要同步。這種技術(shù)成為線程封閉。棧封閉棧封閉是線程封閉的一種特例,在棧封閉中,只能通過局部變量才能訪問對(duì)象。,對(duì)象是正確創(chuàng)建的。 線程封閉 當(dāng)訪問共享的可變數(shù)據(jù)時(shí),通常需要使用同步。一種避免使用同步的方式就是不共享數(shù)據(jù)。如果僅在單線程內(nèi)訪問數(shù)據(jù),就不要同步。這種技術(shù)成為線程封閉(Thread Confine...

    Richard_Gao 評(píng)論0 收藏0
  • 【J2SE】java并發(fā)編程實(shí)戰(zhàn) 讀書筆記( 一、二、三章)

    摘要:發(fā)布的對(duì)象內(nèi)部狀態(tài)可能會(huì)破壞封裝性,使程序難以維持不變性條件。不變性線程安全性是不可變對(duì)象的固有屬性之一??勺儗?duì)象必須通過安全方式來發(fā)布,并且必須是線程安全的或者有某個(gè)鎖保護(hù)起來。 線程的優(yōu)缺點(diǎn) 線程是系統(tǒng)調(diào)度的基本單位。線程如果使用得當(dāng),可以有效地降低程序的開發(fā)和維護(hù)等成本,同時(shí)提升復(fù)雜應(yīng)用程序的性能。多線程程序可以通過提高處理器資源的利用率來提升系統(tǒng)的吞吐率。與此同時(shí),在線程的使用...

    QLQ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<