首頁  >  文章  >  Java  >  Java中關於單例模式線程安全問題的解決方法

Java中關於單例模式線程安全問題的解決方法

黄舟
黄舟原創
2017-09-15 10:36:301571瀏覽

這篇文章主要介紹了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實例。

以上是Java中關於單例模式線程安全問題的解決方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn