小結**
發布物件:使乙個物件能夠被當前範圍之外的**所使用,日常開發中比較常見的比如通過類的非私有方法返回物件的引用,或者通過公有的靜態變數發布物件等都屬於發布物件
物件逸出: 首先需要明確的是物件逸出是一種錯誤的發布方式。當乙個物件還沒有構造完成時,就使它被其他執行緒所見。
package com.artisan.example.publish;
import com.artisan.anno.notthreadsafe;
import lombok.extern.slf4j.slf4j;
@slf4j
@notthreadsafe
public
class
unsafepublishobjectdemo
public
static
void
main
(string[
] args)
",name)
;// 假設有第二個執行緒去修改name屬性的值
string name2 = unsafepublishobjectdemo.
getname()
; name2 =
"小工匠"
; log.
info
("name:{}"
,name2);}
}
上面的**裡,通過new物件初始化了unsafepublishobjectdemo
物件。然後呼叫getname()
方法獲取到了私有屬性的引用,這樣就可以在其他任何執行緒中,修改該屬性的值。這樣將會導致我們在其他執行緒中,獲取該屬性的值時是不確定的,因為並不能得知該屬性的值是否已被其他執行緒所修改過,所以這就是不安全的物件發布。
package com.artisan.example.publish;
import com.artisan.anno.notrecommand;
import com.artisan.anno.notthreadsafe;
import lombok.extern.slf4j.slf4j;
/** *
* 物件逸出示例,在物件構造完成之前,不可以將其發布
* @author yangshangwei
* */
@slf4j
@notthreadsafe
@notrecommand
public
class
objectescapedemo
private
class
innerclass
", objectescapedemo.
this
.thiscanbeescape);}
}public
static
void
main
(string[
] args)
}
上述**中,內部類的構造器裡包含了對封裝例項的隱含引用,這樣在物件沒有被正確構造完成之前就會被發布,由此會導致不安全的因素在裡面。其中乙個就是導致this引用在構造期間逸出的錯誤,它是在建構函式構造過程中啟動了乙個執行緒,無論是顯式啟動還是隱式啟動,都會造成this引用的逸出。
新執行緒總會在所屬物件構造完畢之前就已經看到它了,所以如果要在建構函式中建立執行緒,那麼不要啟動它,而是應該採用乙個專有的start,或是其他初始化的方式統一啟動執行緒。
這裡其實我們可以使用工廠方法和私有建構函式來完成物件建立和***的註冊等等來避免不正確的發布。
不正確的發布可變物件導致的兩種錯誤:
併發程式設計(七) 安全發布物件
發布物件是指使乙個物件能夠被當前範圍之外的 所使用 物件逸出是一種錯誤的發布,指當乙個物件還沒有構造完成時,就使它被其他執行緒所見 slf4j public class escape private class innerclass escape.this thiscanbeescape publi...
併發學習(十) 安全物件發布
平時我們建立的物件往往不會考慮到安全物件的概念,這可能比較陌生,但是你面試的時候面試官很喜歡問你執行緒安全的單例模式,而這就是相關的知識點 發布 使物件能夠在除了當前作用域之外的地方使用 最常用的方法 將物件的引用儲存到乙個公有的靜態變數中,讓任何類和執行緒都能看到該物件。逸出 某個物件不應該被發布...
(二)Java併發學習筆記 安全發布物件
上邊關於逸出的概念講述的很是模糊,下面列舉幾個逸出的示例。通過靜態變數引用逸出 public static setknownsecrets public void initialize 上邊 示例中,呼叫initialize方法,發布了knowsecrets物件。當你向knowsecrets中新增乙...