2 回答

TA貢獻1812條經驗 獲得超5個贊
你的問題都看了,其實就是線程安全問題,跟spring并沒有什么關系。需要清楚兩點
線程安全問題是多線程訪問共享數據才會存在的,這包括兩種情況,一是多線程訪問單例的成員變量,二是多線程訪問靜態變量(數據庫這里這就不算了)
線程內部不會產生安全問題,從java內存模型來看,一個線程對于對象的操作流程應該是,訪問主存中的對象并復制到工作內存當中,在工作內存中對副本做相應操作,操作完成后再寫入主存,線程見會產生線程安全問題,正是因為一個線程在操作工作內存中的副本時,在寫入主存之前,其他線程是不可見的,所以會產生問題,而線程內部,無論哪個方法怎么執行,對副本都是可見的,你說的兩種情況其實也是不存在的,情況1,如果你在一個線程中,一個方法執行到一半,去執行另一個方法,代碼怎么寫?肯定是在第一個方法中調用第二個方法,那么第二個方法執行完,第一個方法的后半部分肯定要接著第二個的邏輯寫,還接著第一個方法的前一半寫,那就是代碼寫錯了,情況2相同
這兩點應該可以解答你所有的問題

TA貢獻1784條經驗 獲得超7個贊
Spring作為一個IOC/DI容器,幫助我們管理了許許多多的“bean”。但其實,Spring并沒有確保這些對象的線程安全,需要由開發者自己編寫解決線程安全問題的代碼。
Spring對每個bean提供了一個scope屬性來表示該bean的作用域。它是bean的生命周期。
我們知道在一般情況下,只有無狀態的Bean才可以在多線程環境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非線程安全狀態采用ThreadLocal進行處理,讓它們也成為線程安全的狀態,因為有狀態的Bean就可以在多線程中共享了。
一般的Web應用劃分為展現層、服務層和持久層三個層次,在不同的層中編寫對應的邏輯,下層通過接口向上層開放功能調用。在一般情況下,從接收請求到返回響應所經過的所有程序調用都同屬于一個線程。
ThreadLocal是解決線程安全問題一個很好的思路,ThreadLocal是一個為線程提供線程局部變量的工具類。它的思想也十分簡單,就是為線程提供一個線程私有的變量副本,這樣多個線程都可以隨意更改自己線程局部的變量,不會影響到其他線程。不過需要注意的是,ThreadLocal提供的只是一個淺拷貝,如果變量是一個引用類型,那么就要考慮它內部的狀態是否會被改變,想要解決這個問題可以通過重寫ThreadLocal的initialValue()函數來自己實現深拷貝,建議在使用ThreadLocal時一開始就重寫該函數。
ThreadLocal通過為每個線程提供一個獨立的變量副本解決了變量并發訪問的沖突問題。在很多情況下,ThreadLocal比直接使用synchronized同步機制解決線程安全問題更簡單,更方便,且結果程序擁有更高的并發性。
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。
或者說:一個類或者程序所提供的接口對于線程來說是原子操作或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題。
- 2 回答
- 0 關注
- 114 瀏覽
添加回答
舉報