2015-09-28 130 views
4

Java Concurrency In Practice, Section 2.1,它指出:無狀態對象始終是線程安全的?

無狀態的對象始終是線程安全的。

,並給出了下面的類爲例:

@ThreadSafe 
public class StatelessFactorization implements Servlet { 
    public void service(ServletRequest req, ServletResponse resp){ 
     BigInteger i = extractFromRequest(req); 
     BigInteger[] factors = factor(i); 
     encodeIntoResponse(resp, factors);  // <-- isn't it possible for resp to be 
               //  modified by mult. threads at once? 
    } 
} 

問:

如上面的代碼所示,如​​果多個線程試圖修改同一個ServletResponse變量會發生什麼。

從我對內存分配的理解來看,上面的類看起來並不完全是線程安全的。

雖然對ServletRequestServletResponse的引用放置在調用線程的本地堆棧上,但實際對象存儲在堆上 - 它在所有線程之間共享。

回答

5

這裏的無狀態對象是StatelessFactorization類。它是無狀態的,因爲它沒有自己的狀態,即它沒有實例字段。因此這個對象是線程安全的。 resp是實現接口的另一個對象,它可能或可能不是線程安全的。這裏不討論resp的線程安全性。

+0

這是有道理的我猜,但它似乎令人困惑,他們會用這個例子 - 因爲調用'StatelessFactorization'方法可能會導致不是線程安全的東西。使用原始的(或任何不可變的)參數對我來說會不那麼困惑。 – bcorso

+0

@bcorso,我猜這本書的作者想要展示一些接近現實世界的例子。當然,我不能確切地說。 –

3

當您發出將要由servlet處理的HTTP請求時,將調用其service方法。如果您有多個客戶端同時發出多個請求,則每個請求可能由不同的線程處理。但是,每個線程將收到的ServletRequestServletResponse的實例爲不同,因此您不會有多個線程修改這些對象的相同實例。每個線程修改它們自己的實例。當然,這不是魔術般發生的,您的servlet容器(例如Tomcat)是在這種特定情況下爲您處理線程創建和分配這些實例的人。

這是一個令人困惑的例子,因爲你不能假設你總是可以在該方法內部修改任何你想要的東西,並且所有東西都會神奇般的線程安全。但是,這是一個有趣的方法示例,通常由現實世界中的多個線程執行。

+0

感謝您的額外環境! – bcorso

相關問題