您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關CAS非鎖怎樣實現單例的一個缺陷,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
今天我們要說的是,無鎖實現單例模式,以及這種 CAS 實現的單例的缺點。
傳統的 7 種單例模式大致如下:
它們都是用鎖來實現。但是如果在面試過程中面試官問你如何使用非鎖來實現一個單例呢?
答案就是下圖這種實現。
這是網上一位大牛的實現,他的這種非鎖 CAS 實現的單例,挺好的。但是平時可能沒有人使用,比用鎖稍微復雜了一點,這也是為什么沒有被列入單例模式的 7 大寫法之中了。我在他的基礎上,也就是他的構造方法里添加了兩行代碼。
我主要是想看看它到底是實例化了幾次。加上這兩行代碼,可以方便我觀察控制臺,和統計實例化的總次數。
然后,我的測試代碼如下:
關于 CountDownLatch 有不會的,可以看我的《CountDownLatch 壓測教程》一文。
我這里主要是想壓測一下,非鎖 CAS 單例模式是否會創建多次對象。
運行上面的 main 方法,我截圖了一下最終結果。
CAS 以原子方式更新內存中相應的值,從而保證了多線程環境下共享變量更新操作的同步。的確,這種方式可以保證每次調用getInstance() 方法得到的一定是同一個實例。因此,從功能實現的角度來看,這種做法達到了預期的目的。但是,經過分析和測試,卻發現這種方式有一些預期之外的弊病:可能會創建不止一個對象。
CAS 本身的操作的確是原子方式,但是包裝 CAS 指令的方法并非是全程同步的,當然,在包含 CAS 指令的方法開始調用之前,參數計算過程中更不是互斥執行的!當一個線程測試 instance.get() == null 得到 true 之后,往下它就一定會調用 new Singleton()。因為,這并不是 CAS 方法的一部分,而是它的參數。在調用一個方法之前,需要先將其參數壓入棧,當然,需要先計算參數表達式,因此,產生如上結果也就不難預料了。
CAS 與鎖的區別在于,它是非阻塞的,也就是說,它不會去等待一個條件,而是一定會去執行,結果要么成功,要么失敗。它的操作時間是可預期的。如果我們的目的是一定要成功執行 CAS,那就需要不斷循環執行直至成功,同時,建立在成功預期之上大量的準備工作是值得的,但是,如果我們不希望操作一定成功,那為成功操作而做的準備工作就浪費掉了。
上述就是小編為大家分享的CAS非鎖怎樣實現單例的一個缺陷了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。