Java多線程——不變性與安全發布

1、不變性

  某個對象在被創建后其狀態就不能被修改,那么這個對象就稱為不可變對象,不可變對象一定是線程安全的。不可變對象很簡單。他們只有一種狀態,并且該狀態由構造函數來控制。

  當滿足以下條件時,對象才是不可變的:(1)、對象創建以后其狀態就不能改變;(2)、對象的所有域都是final類型;(3)、對象是正確創造的(在對象創建期間,this引用沒有溢出)。

1.1 final域

  關鍵字final用于構造不可變對象,final類型的域是不能修改的(但是final域所引用的對象是可變的,那么這些引用的對象是可以修改的),即使對象是可變的,通過將可變對象的某些域聲明為final類型,相當于告訴維護人員這些域是不可變化的。

?

2、正確發布一個對象

  正確發布一個對象遇到的兩個問題:(1)引用本身要被其他線程看到;(2)對象的狀態要被其他線程看到。

  在多線程編程中,首要的原則,就是要避免對象的共享,因為如果沒有對象的共享,那么多線程編寫要輕松得多,但是,如果要共享對象,那么除了能夠正確的將構造函數書寫正確外,如何正確的發布也是一個很重要的問題。

  我們看下面的代碼:

 1 public class Client {
 2     public Holder holder;
 3     
 4     public void initialize(){
 5         holder = new Holder(42);
 6     }
 7 }
 8 
 9 
10 public class Holder {
11     int n;
12     public Holder(int n) {
13         this.n = n;
14     }
15     public void assertSanity() {
16         if(n != n)
17              throw new AssertionError("This statement is false.");
18     }
19 }
View Code

  在Client類中,Holder對象被發布了,但是這是一個不正確的發布。由于可見性問題,其他線程看到的Holder對象將處于不一致的狀態,即使在該對象的構成構函數中已經正確的該構建了不變性條件,這種不正確的發布導致其他線程看到尚未創建完成的對象。主要是Holder對象的創建不是原子性的,可能還未構造完成,其他線程就開始調用Holder對象。

由于沒有使用同步的方法來卻確保Holder對象(包含引用和對象狀態都沒有)對其他線程可見,因此將Holder成為未正確發布。問題不在于Holder本身,而是其沒有正確的發布。上面沒有正確發布的可能導致的問題:

  • 別的線程對于holder字段,可能會看到過時的值,這樣就會導致空引用,或者是過時的值(即使holder已經被設置了)(引用本身沒有被別的線程看到)
  • 更可怕的是,對于已經更新holder,及時能夠看到引用的更新,但是對于對象的狀態,看到的卻可能是舊值,對于上面的代碼,可能會拋出AssertionError異常

主要是holder = new Holder(42);這個代碼不是原子性的,可能在構造未完成時,其他線程就會調用holder對象引用,從而導致不可預測的結果。

2.1安全發布常用模式

  要安全的發布一個對象,對象的引用和對象的狀態必須同時對其他線程可見。一般一個正確構造的對象(構造函數不發生this逃逸),可以通過如下方式來正確發布:

  (1)、在靜態初始化函數中初始化一個對象引用

  (2)、將一個對象引用保存在volatile類型的域或者是AtomicReference對象中

  (3)、將對象的引用保存到某個正確構造對象的final類型的域中。

  (4)、將對象的引用保存到一個由鎖保護的域。

  

  在線程安全容器內部同步意味著,在將對象放到某個容器中,比如Vector中,將滿足上面的最后一條需求。如果線程A將對象X放到一個線程安全的容器中,隨后線程B讀取這個對象,那么可以確保可以確保B看到A設置的X狀態,即便是這段讀/寫X的應用程序代碼沒有包含顯示的同步。下面容器內提供了安全發布的保證:

  (1)、通過將一個鍵或者值放入Hashtable、synchronizedMap或者ConcurrentMap中,可以安全將它發布給任何從這些容器中訪問它的線程。

  (2)、通過將某個元素放到Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchroizedList,可以將該元素安全的發布到任何從這些容器中訪問該元素的線程。

  (3)、通過將元素放到BlockingQueue或者是ConcrrentLinkedQueue中,可以將該元素安全的發布到任何從這些訪問隊列中訪問該元素的線程。

  通常,要發布一個靜態構造的對象,最簡單和最安全的方式是使用靜態初始化器:?public static Holder = new Holder(42);

  靜態初始化器由JVM在類的初始化階段執行,由于JVM內部存在同步機制,所以這種方式初始化對象都可以被安全的發布。對于可變對象,安全的發布之時確保在發布當時狀態的可見性,而在隨后的每次對象的訪問時,同樣需要使用同步來確保修改操作的可見性。

  

轉載于:https://www.cnblogs.com/Hxinguan/p/7471461.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371332.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371332.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371332.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

中tr不能顯示字符_垃圾文本識別中基本操作指南和錯誤總結,第三部分

創建模型需要用到機器學習的庫,所以我們先下載sklearn庫sklearn庫下載完成后再輸入庫文件,就可以完美運行。然后就是劃分測試集和訓練集,需要注意的是,在從數據處理函數中導入數據時,足足運行了有將近30多秒&#xff0…

mvc后臺post發送json數據

代碼比較簡單&#xff0c;不廢話&#xff0c;直接上代碼&#xff1a; /// <summary>/// 提交json數據&#xff0c;并接收/// </summary>/// <param name"apipath">要請求的服務器地址</param>/// <param name"jsonStr">要提…

(轉載)20分鐘讀懂程序集

轉自&#xff1a;http://www.cnblogs.com/damonlan/p/3221347.html 說到程序集&#xff0c;我剛開始對這個名詞特別的郁悶&#xff01;~。然后 前些天花了些時間 好好讀了一下&#xff0c;現在比較清晰了&#xff0c;把一些書上看到的 記下來&#xff0c;以饗讀者。希望沒浪費你…

大數據胸_喂母乳會導致胸下垂?!你被這個謠言騙了多少年?

很多人認為&#xff0c;給寶寶喂奶會導致胸下垂。有些愛美的媽媽&#xff0c;甚至在寶寶出生6個月后就著急斷奶。那么&#xff0c;喂奶真的會導致胸下垂么&#xff1f;給大家講兩個真實的調查結果哈~2004年的一次針對496名新媽媽的調查結果顯示&#xff0c;有75%的母乳喂養母親…

Spring Shell項目發布

Spring Source昨天發布了Spring Shell 。 Spring Shell是一個交互式Shell&#xff0c;可以使用基于Spring的編程模型輕松地通過命令進行擴展。 它是通過除去OSGi依賴項從Spring Roo項目中提取的&#xff0c;并變成了一個獨立項目。 這使得那些只希望使用交互式外殼功能的人更容…

自制ACL+DHCP實驗(初版)

&#xff08;實驗用gns模擬器&#xff09; ACL 實驗拓撲&#xff1a; 實驗要求&#xff1a; 1.1.1.1→3.3.3.3 不通 11.11.11.11→3.3.3.3 通 2.2.2.2→3.3.3.3 通 實驗步驟&#xff1a; 步驟一&#xff1a;基本配置 R1&#xff1a; R1#conf t R1(config)#int lo0 R1(config-if…

pil 圖像最大值_第97天:圖像庫 PIL(二)

上節我們講了 Python 的圖像處理庫 PIL 的基本圖像處理功能&#xff0c;打開了 PIL 的神秘面紗。這節我們接著講 PIL 的 Image 模塊的常用方法。Image 模塊的方法convertImage.convert(modeNone, matrixNone, ditherNone, palette0, colors256)參數說明&#xff1a;mode&#x…

c#的委托用法delegate

轉載于:https://www.cnblogs.com/douzujun/p/6555886.html

yii2.0

yii是一個高性能的適用于開發web2.0應用的框架&#xff0c;它自帶豐富的功能&#xff0c;包括mvc&#xff0c;dao/aciverecord&#xff0c;緩存&#xff0c;身份驗證和基于角色的訪問控制&#xff0c;腳手架&#xff0c;測試等&#xff0c;可顯著縮短開發時間yii只加載你需要的…

Java中常見的代碼沖突

在工作中&#xff0c;最近我對現有Java項目進行了代碼清理。 完成該練習后&#xff0c;我可以看到在代碼中一次又一次地發生了一組常見的代碼沖突。 因此&#xff0c;我想出了此類常見違規的清單&#xff0c;并與同行分享&#xff0c;以使人們有意識地提高代碼質量和可維護性。…

np讀取csv文件_被 Pandas read_csv 坑了

-- 不怕前路坎坷&#xff0c;只怕從一開始就走錯了方向Pandas 是python的一個數據分析包&#xff0c;納入了大量庫和一些標準的數據模型&#xff0c;提供了高效地操作大型數據集所需的工具。Pandas 就是為解決數據分析任務生的&#xff0c;無論是數據分析還是機器學習項目數據預…

Python 第三方庫 cp27、cp35 等文件名的含義

What does version name ‘cp27’ or ‘cp35’ mean in Python? 如對于 gensim-0.12.4-cp27-none-win_amd64.whl文件名而言&#xff0c;將其文件名拆分的話&#xff0c;含義分別是&#xff1a; 0.12.4 - package version, they may be using semantic versioningcp27 - this p…

JAVA: 序列化

對象序列化 - 一個對象可以被表示為一個字節序列&#xff0c;保存對象的類型信息、對象的數據&#xff0c;還有對象中的數據類型&#xff0c;以便存儲或傳輸。 反序列化 - 將序列化對象寫入文件之后&#xff0c;可以從文件中讀取出來&#xff0c;并且對它進行反序列化&#xff…

尋找隨機的錯誤-一個真實的故事

幾周前&#xff0c;我完成了RapidFTR開源項目的錯誤查找 &#xff0c;這花了我三個晚上。 我認為可能值得分享狩獵的故事。 本文將介紹我的工作。 我將概述我的旅程&#xff0c;以實際找到正在發生的事情的根本原因。 我在本文中的目標是突出顯示可以使用的技術示例&#xff0c…

鈴木uy125摩托車機油_UY125 新瑞夢UM125發布 濟南鈴木于湖南株洲吹響國IV集結號...

?4月18日&#xff0c;濟南鈴木在湖南株洲天臺開元酒店舉行了2019年新品發布會&#xff0c;并于現場發布了兩款極具終端戰略意義的新款國IV車型&#xff0c;分別為定位“實用運動”的全新個性化踏板車型UY125&#xff0c;以及能夠進一步鞏固濟南鈴木在國IV入門級踏板車型領域絕…

473. 核電站問題

★ 輸入文件&#xff1a;nucle.in 輸出文件&#xff1a;nucle.out 簡單對比 時間限制&#xff1a;1 s 內存限制&#xff1a;128 MB 【問題描述】 一個核電站有 N 個放核物質的坑&#xff0c;坑排列在一條直線上。如果連續 M 個坑中放入核物質&#xff0c;則會發生爆炸&…

js判斷時間是早上還是下午_牛奶早上喝好,還是晚上喝好?沒想到“最佳時間”是這個點,顛覆了!...

都說喝牛奶好&#xff0c;要多喝。可什么時間喝牛奶最好呢&#xff1f;是飯前、飯后還是睡前&#xff1f;又或者喝酒前&#xff1f;確實得好好說說。傳言&#xff1a;空腹時身體比較缺能量&#xff0c;牛奶里的蛋白會去提供能量&#xff0c;不會去構成和修復組織(比如修復皮膚)…

Java模因拒絕死亡

也有標題&#xff1b; 我的寵物討厭Java編碼。 有許多Java模因讓我很煩&#xff0c;部分是因為它們總是一個壞主意&#xff0c;但主要是因為人們在找到更好的替代方案后的幾年里仍在繼續使用它們。 使用StringBuffer代替StringBuilder 從2004年開始&#xff0c;用于StringBuf…

Python TK編程第一部分 Hello Again

當你想寫大一點的程序的時候&#xff0c;將你的代碼封裝到一個或者多個類里會是一個不錯的辦法。下面hello world這個例子來自Matt Conway的Tkinter Life Preserver. [python]view plain copy from Tkinter import * class App: def __init__(self, master): …

視網膜脫離oct報告圖_剛剛,愛爾眼科發布關于艾芬醫生診療過程的核查報告

剛剛&#xff0c;愛爾眼科醫院集團發布關于艾芬女士診療過程的核查報告&#xff0c;內容如下&#xff1a;得悉艾芬女士對武漢愛爾眼科醫院白內障診療存疑&#xff0c;愛爾眼科醫院集團高度重視&#xff0c;第一時間成立了工作組奔赴武漢&#xff0c;對事件的診療全過程開展了核…