乙個共享變數被乙個執行緒修改後,另外乙個執行緒能夠正確的獲取到共享變數最新值,此共享變數具有可見性。
缺乏同步的共享變數,在多執行緒訪問中,就可能獲取到失效資料,從而導致不可預見的錯誤。
正常情況下,即使是非同步變數,不同執行緒獲取到的不是最新資料,為失效資料,但至少它是之前存在過的值,這個值曾經出現過,這種就是所謂的最低安全性。jvm將非volatile型別的long和double變數(64位數值)分解為兩個32位操作,多個執行緒修改變數後,可能讀取到不是乙個值的高32位和低32位。
所有執行讀操作和寫操作的執行緒都在同乙個鎖上同步,保證了單個執行緒在修改某變數時對其他執行緒可見。加鎖機制既可以保證可見性,又可以保證原子性。
將變數的通知同步到其他執行緒,但是不要過度依賴此關鍵字提供的可見性,避免在需要對可見性執行複雜判斷的地方使用(依賴變數當前的值),典型用法是檢查某個狀態標誌是否退出迴圈。
發布是使乙個物件能夠在當前作用域之外的**中使用,逸出指發布了不該發布的物件,說白了就是錯誤的發布,導致某物件能夠在指定的作用域之外的地方使用。
不要在建構函式中使this逸出,這一點還不好用文字描述,大概來說在物件構造完成之前(建構函式中),呼叫了this物件的方法,就上書中呼叫了dosomething()一樣,此方法屬於成員方法。另外使用匿名內部類就可以了在這個內部類中包含了thisescape的引用,this.dosomething(),從而導致this的方法在外部可以訪問。
可以參考:
維護執行緒封閉的職責由程式來承擔,使用單執行緒訪問共享變數,由於是單執行緒訪問,所以。
將變數儲存在thread中,封閉在每個執行緒內部,確保其他執行緒無法訪問。
物件的狀態在確定之後無法修改,成為不可變物件,物件的狀態不可變後,當時是執行緒安全的。要確保物件不可變,有三個必要條件:1、所有的域都使用final修飾2、正確的構造物件,保證this引用沒有逸出3、物件建立以後狀態就不可改變
final型別的域是不可修改的。另,變數宣告時除非需要更大的作用域,否則都應該宣告為私有域,除非變數時可變的物件,否則都應該使用final修飾宣告為不可變物件。
由於是不可變物件,所以在更新狀態的時候,需要重新建立不可變物件,這時使用volatile來保證執行緒能夠看到最新的狀態。
多個執行緒安全的共享變數
holder不是乙個不可變物件,它的成員變數沒有使用同步,導致多個執行緒都可以不安全的訪問。書上說如果使用fianl修飾holder中的n就可以解決安全發布的問題,大概意識就是說就變為不可變物件。
直接上書上的結論吧,任何執行緒都可以在不需要額外同步的情況下安全地訪問不可變物件,即使在發布這些物件時沒有使用同步。
物件的引用和物件的狀態必須同時對其他執行緒可見,才是可變物件的安全發布:
使用靜態初始化函式初始化乙個物件的引用,靜態初始化,只會在類載入的時候執行一次,所以。
將物件引用的域儲存到volatile域或者atomicreference物件中。
將物件的引用儲存到某個正確構造物件的final型別域中。
將物件引用儲存在有鎖保護的乙個域中。
可變物件在構造出來之後,沒有改變的需求,形成事實上的不可變物件
不僅需要安全的發布,狀態的修改也需要保證其的安全性。使用同步機制。
發布的物件所具有的正確的訪問方式,通過公有介面,或者特定的鎖等。
併發程式設計實戰筆記 第2章
1 無狀態的物件一定是執行緒安全的。2 不恰當的執行時序,出現不正確的結果,定義為競態條件。3 單狀態變數,使用原子型別 4 多狀態變數互動,使用synchronzied,包括2部分,1 要鎖定的物件 2 要保護的 塊。被保護的 塊,操作可看成乙個事務。5 內建鎖是可重入的,也就是自己去獲取自己已經...
《java併發程式設計實戰》筆記(第4章)
十九 設計執行緒安全的類 在設計執行緒安全類的過程中,需要包含以下三個基本要素 1.找出構成物件狀態的所有變數 2.找出約束狀態變數的不變性條件 3.建立物件狀態的併發訪問管理策略。19.1 設計執行緒安全的類 1.類的不變性條件和後驗條件約束了在物件上有哪些狀態和狀態轉換是有效的。2.某些方法還包...
JavaScript物件程式設計 第3章
物件擁有屬性和方法,屬性各種資料型別,方法對屬性中的資料進行操作。var 日期物件 new date var 日期物件 new date 毫秒數 var 日期物件 new date 字串 var 日期物件 new date 年 月 日等引數 to方法 tolocalestring togmtstri...