Java 單例模式線程安全問題
Java 單例模式線程安全問題
SpringIOC容器默認(rèn)提供bean的訪問作用域是單例模式。即在整個(gè)application生命周期中,只有一個(gè)instance。因此在多線程并發(fā)下,會(huì)有線程安全風(fēng)險(xiǎn)。我們?cè)贛VC框架下的servlet就是線程安全的。由于該servlet是在客戶端,多并發(fā)相對(duì)少,但是對(duì)于web service端,需要考慮到。
ThreadLocal類:為每一個(gè)線程提供了一個(gè)獨(dú)立的變量(實(shí)例)副本,從各將各個(gè)不同的實(shí)例訪問isolation。
在同步鎖機(jī)制中,后來者線程等待先行線程完成后,才能訪問該成員變量。而ThreadLocal實(shí)現(xiàn)實(shí)例的復(fù)制而隔離對(duì)象訪問數(shù)據(jù)沖突。同時(shí)也能夠少量解決scope為prototype訪問模式下大量實(shí)例生命周期管理的消耗和負(fù)擔(dān)。是“以時(shí)間換空間”和“以空間換時(shí)間”的兩種實(shí)現(xiàn)。前者僅提供唯一變量,讓不同的線程排隊(duì)訪問,而后者為每一個(gè)線程都提供了一份拷貝,因此可以同時(shí)訪問而互不影響,同時(shí)該拷貝存儲(chǔ)于內(nèi)存中,下次再次訪問時(shí)候不再重新生成實(shí)例,減少服務(wù)器資源消耗。
我們知道在一般情況下,只有無狀態(tài)的Bean才可以在多線程環(huán)境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域。就是因?yàn)镾pring對(duì)一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非線程安全狀態(tài)采用ThreadLocal進(jìn)行處理,讓它們也成為線程安全的狀態(tài),因?yàn)橛袪顟B(tài)的Bean就可以在多線程中共享了。
線程安全問題:由全局變量及靜態(tài)變量引起,若每個(gè)線程中對(duì)全局變量、靜態(tài)變量只有讀操作,而無寫操作,一般來說,這個(gè)全局變量是線程安全的;若有多個(gè)線程同時(shí)執(zhí)行寫操作,一般都需要考慮線程同步,否則就可能影響線程安全。
1) 常量始終是線程安全的 (值恒定)
2)每次調(diào)用方法前都新建一個(gè)實(shí)例是線程安全的。(不同實(shí)例相互隔離)
3)局部變量是線程安全的(隔離)
因?yàn)槊繄?zhí)行一個(gè)方法,都會(huì)在獨(dú)立的空間創(chuàng)建局部變量,它不是共享的資源。局部變量包括方法的參數(shù)變量和方法內(nèi)變量。
有狀態(tài):有數(shù)據(jù)存儲(chǔ)、更改功能。有狀態(tài)對(duì)象(Stateful Bean),有實(shí)例變量的對(duì)象 ,可以保存數(shù)據(jù),是非線程安全的。
無狀態(tài):就是一次操作,不能變更數(shù)據(jù)。無狀態(tài)對(duì)象(Stateless Bean),沒有實(shí)例變量的對(duì)象,不能保存數(shù)據(jù),是不變類,是線程安全的。在spring中單例模式是共享實(shí)例,以達(dá)到提高性能。有狀態(tài)的Bean,多線程環(huán)境下不安全,那么適合用Prototype原型模式。Prototype: 每次對(duì)bean的請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的bean實(shí)例。
如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
springboot業(yè)務(wù)功能實(shí)戰(zhàn)之告別輪詢websocket的集成使用
WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于springboot業(yè)務(wù)功能實(shí)戰(zhàn)之告別輪詢websocket的集成使用,需要的朋友可以參考下2022-10-10idea中maven本地倉庫jar包打包失敗和無法引用的問題解決
本文主要介紹了idea中maven本地倉庫jar包打包失敗和無法引用的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Java編程用兩個(gè)棧實(shí)現(xiàn)隊(duì)列代碼分享
這篇文章主要介紹了Java編程用兩個(gè)棧實(shí)現(xiàn)隊(duì)列代碼分享,具有一定參考價(jià)值,這里給大家分享下,供需要的朋友了解。2017-10-10Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例
這篇文章主要介紹了Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java設(shè)計(jì)模式之Iterator模式介紹
所謂Iterator模式,即是Iterator為不同的容器提供一個(gè)統(tǒng)一的訪問方式。本文以java中的容器為例,模擬Iterator的原理。需要的朋友可以參考下2013-07-07