細說線程安全

一、什麼是線程安全?

  若是一個對象構造完成後,調用者無需額外的操做,就能夠在多線程環境下隨意地使用,而且不發生錯誤,那麼這個對象就是線程安全的。安全

二、線程安全的注意事項

  • 對『線程安全性』的討論必須創建在對象內部存在共享變量這一前提,若對象在多條線程間沒有共享數據,那這個對象必定是線程安全的!
  • 咱們一般所說的『線程安全』即爲『相對的線程安全』,JDK中標註爲線程安全的類一般就是『相對的線程安全』

三、實現線程安全的幾種方法

  • 互斥同步
    • 同步是指在同一時刻只能由一個線程操做共享變量
    • 互斥會引發阻塞,當一條線程請求一個已經被另外一線程使用的鎖時,就會進入阻塞態;而進入阻塞態會涉及上下文切換。所以,使用互斥來實現同步的開銷是很大的。
    • 互斥同步(阻塞式同步)是一種『悲觀鎖』,即它認爲老是存在多條線程競爭資源的狀況,所以它無論當前是否是真的有多條線程在競爭共享資源,它老是先上鎖,而後再處理。
    • Java中有兩種實現互斥同步的方式:synchronized和ReentrantLock。
  • 非阻塞同步
    • 它是一種『樂觀鎖』,即它老是認爲當前沒有線程使用共享資源,所以它無論當前的狀態,直接操做共享資源,若發現產生了衝突,那麼再採起補償措施(如:CAS的補償措施就是不斷嘗試,直到不發生衝突爲止),這種方式線程無需進入阻塞態(掛起態),所以稱爲『非阻塞同步』。
    • JUC中各類整形原子類的自增、自減等操做就使用了CAS。
    • CAS操做過程:CAS操做存在3個值:共享變量V、預期的舊值A、新值B,若V與A相同,則將V更新成B,不然就不更新,繼續循環比較,直到更新完成爲止。
    • CAS操做可能引起的問題:ABA問題。 若V一開始的值爲A,但在準備賦新值的過程當中A變成了B,又變成了A,而CAS操做誤認爲V沒有被改過。
相關文章
相關標籤/搜索