什麼是線程安全?

給「線程安全」下定義是件很是棘手的事兒。隨便Google一下,就能獲得成千上萬像這樣的定義:html

1.「線程安全」的代碼是指在多線程同時執行的狀況下,依然能正常工做的代碼。java

2.一段代碼,若是在多線程同時執行的狀況下,能以一種安全的方式操做共享數據結構,它就是線程安全的。安全

還有不少相似的定義。數據結構

你不覺着相似上面這種定義非但沒有傳達出有用的信息,甚至讓本身更加迷惑嗎?儘管這樣,這些定義仍是被你們無奈的接受了,由於它並無錯。只是,他們沒能提供任務實質性的幫助或看法。多線程

咱們怎麼區別「線程安全」的類和不安全的類?甚至說「安全」到底什麼意思?併發

在線程安全中,什麼是「正確性」?less

任何對「線程安全」的合理定義,其核心都是在說「正確性」的概念。因此在理解線程安全以前,咱們先來搞懂什麼是「正確性」。post

正確性意味着一個類要符合它的規範

一個好的類規範會明確規定出類在某個時刻的狀態,以及對它進行一些操做後的後置條件(postcondition)。可是,一般咱們並不能爲咱們的類提供充分的規範說明,那咱們怎麼知道他們是否正確執行了?咱們並不能知道,可是這並不能阻止咱們去使用它,一旦咱們說服了本身「這些代碼能正確工做」。這種「代碼信任」就很是接近咱們要說的「正確性」。學習

如今咱們能夠給「線程安全」下一個不那麼繞的定義:線程

一個類在多線程併發訪問時仍能保證行爲的正確性,那麼它就是線程安全的類。

一個線程安全的類在被多線程併發訪問時仍然能正確的執行,無論這些線程是順序執行仍是錯終複雜的交叉執行。而且,被調用的代碼中不須要額外的添加線程同步代碼。

換句話說,線程安全的類在多線程環境下和單線程環境下運行結果老是一致的。線程安全的類在內部已經處理好了任何有關線程同步的問題,而調用者再也不須要考慮線程安全問題。

例子:無狀態的Servlet

關於線程安全的類有個很好的例子,就是沒有全局變量的java Servlet。這樣的Servlet是無狀態的。

public class StatelessFactorizer implements Servlet
{
   public void service(ServletRequest req, ServletResponse resp)
   {
       BigInteger i = extractFromRequest(req);
       BigInteger[] factors = factor(i);
       encodeIntoResponse(resp, factors);
   }
}

StatelessFactorizer類每次執行後的瞬時狀態只存在於service方法的局部變量中,而局部變量存儲在線程私有的線程棧中。一個線程訪問StatelessFactorizer不會影響到另外一個線程訪問StatelessFactorizer的結果,由於這兩個線程沒有共享狀態,就好像他們在訪問不一樣的實例。因爲,一個線程對無狀態對象的操做不會影響到其餘線程的操做的正確性,因此無狀態對象是線程安全的。

以上就是很重要的「線程安全」的概念。

 

學習愉快!

相關文章
相關標籤/搜索