1. 程式人生 > >Java 單例模式執行緒安全問題

Java 單例模式執行緒安全問題

Java 單例模式執行緒安全問題

 更新時間:2017年09月14日 11:30:42   作者:flycw    我要評論

 

這篇文章主要介紹了Java 單例模式執行緒安全問題的相關資料,希望通過本文大家能瞭解掌握單例模式中執行緒安全的使用方法,需要的朋友可以參考下

Java 單例模式執行緒安全問題

SpringIOC容器預設提供bean的訪問作用域是單例模式。即在整個application生命週期中,只有一個instance。因此在多執行緒併發下,會有執行緒安全風險。我們在MVC框架下的servlet就是執行緒安全的。由於該servlet是在客戶端,多併發相對少,但是對於web service端,需要考慮到。

ThreadLocal類:為每一個執行緒提供了一個獨立的變數(例項)副本,從各將各個不同的例項訪問isolation。
在同步鎖機制中,後來者執行緒等待先行執行緒完成後,才能訪問該成員變數。而ThreadLocal實現例項的複製而隔離物件訪問資料衝突。同時也能夠少量解決scope為prototype訪問模式下大量例項生命週期管理的消耗和負擔。是“以時間換空間”和“以空間換時間”的兩種實現。前者僅提供唯一變數,讓不同的執行緒排隊訪問,而後者為每一個執行緒都提供了一份拷貝,因此可以同時訪問而互不影響,同時該拷貝儲存於記憶體中,下次再次訪問時候不再重新生成例項,減少伺服器資源消耗。 

我們知道在一般情況下,只有無狀態的Bean才可以在多執行緒環境下共享,在Spring中,絕大部分Bean都可以宣告為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非執行緒安全狀態採用ThreadLocal進行處理,讓它們也成為執行緒安全的狀態,因為有狀態的Bean就可以在多執行緒中共享了。

執行緒安全問題:由全域性變數及靜態變數引起,若每個執行緒中對全域性變數、靜態變數只有讀操作,而無寫操作,一般來說,這個全域性變數是執行緒安全的;若有多個執行緒同時執行寫操作,一般都需要考慮執行緒同步,否則就可能影響執行緒安全。

1) 常量始終是執行緒安全的 (值恆定)
2)每次呼叫方法前都新建一個例項是執行緒安全的。(不同例項相互隔離)
3)區域性變數是執行緒安全的(隔離)

因為每執行一個方法,都會在獨立的空間建立區域性變數,它不是共享的資源。區域性變數包括方法的引數變數和方法內變數。

有狀態:有資料儲存、更改功能。有狀態物件(Stateful Bean),有例項變數的物件  ,可以儲存資料,是非執行緒安全的。

無狀態:就是一次操作,不能變更資料。無狀態物件(Stateless Bean),沒有例項變數的物件,不能儲存資料,是不變類,是執行緒安全的。在spring中單例模式是共享例項,以達到提高效能。有狀態的Bean,多執行緒環境下不安全,那麼適合用Prototype原型模式。Prototype: 每次對bean的請求都會建立一個新的bean例項。

如有疑問請留言或者到本站社群交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支援!