我目前正在處理代碼,其中有一個由多個線程使用的單例,並且在單例的函數中用於訪問數據庫的TransactionTemplate和SimpleJdbcTemplate的兩個字段除外。Spring TransactionTemplate和SimpleJdbcTemplate是否線程安全?
這是安全的還是我應該創建一個新的模板,只要我需要一個?
我目前正在處理代碼,其中有一個由多個線程使用的單例,並且在單例的函數中用於訪問數據庫的TransactionTemplate和SimpleJdbcTemplate的兩個字段除外。Spring TransactionTemplate和SimpleJdbcTemplate是否線程安全?
這是安全的還是我應該創建一個新的模板,只要我需要一個?
SimpleJdbcTemplate只包裝一個JdbcTemplate,所以it's thread-safe,就像the TransactionTemplate一樣。
Actualy 不是。查看源代碼以獲取證明。至少TransactionTemplate有非最終成員transactionManager可能是不可見已經創建的線程。此外,它從DefaultTransactionDefinition派生所有非final和publicaly可變成員。
在實際情況下,在負載下的動態容器(如OSGI)可以在TransactionTemplate中使用事務管理器時獲得NPE。特別是如果你創建TransactionTemplate本身(而不是Spring上下文)。這是因爲工作線程(例如Web請求處理器)已經被創建並且變暖(具有自己的線程綁定的CPU緩存)。當在init線程中創建新的TransactionTemplate時,沒有執行內存屏障來刷新線程綁定(或CPU核心綁定)緩存。在極少數情況下,新創建的TransactionTemplate的成員可能對'舊'線程不可見。
運行Web服務熱更新後,生產中的analogios(不完全是TransactionTemplate,但帶有RetryTemplate)生產錯誤。需要說的是,我們在Spring Context創建的實例中沒有看到這樣的錯誤,可能是因爲在上下文初始化時執行了全局同步。
幾乎所有的Spring模板類都是可變的,並且內部沒有顯式的同步。爲什麼文檔說它是線程,但我不明白。
您可能會因爲在JMM中包含對該模板的引用而導致包含對* Template的引用的最後一個字段的最終字段來保護自己(請參閱附加鏈接):「此外,引用的任何其他對象或數組的可見值那些最終領域將至少與最終領域一樣最新。「
在這種情況下,如果你沒有改變* Template實例的狀態,它就是「線程安全」的。不是通過課程設計本身,而是通過具體的使用和JMM屬性。
+1用於引用實際文檔... – pap