一個java併發原子類AtomicBoolean解析

如果看過我之前的文章都知道這幾天一直在更新java多線程這塊的知識點,因為這塊的知識點確實是比較多而且也別繁雜,因此對於java多線程基礎知識點也會在兩個多月的時間全部寫完,這篇文章主要是針對java併發包下的一個原子類AtomicBoolean的講解。

一、為什麼使用AtomicBoolean?

我們平時一般都是使用的boolean來表示布爾變量,但是在多線程情況下boolean是非線程安全的。為什麼是非線程安全的呢?我們看下面的這個例子:

一個java併發原子類AtomicBoolean解析

大家可以看到,這個操作好像並沒有什麼問題,我們使用了synchronized關鍵字對flag對象進行上鎖,這時候同一時刻就只能有一個線程去運行test方法中的代碼了。如果你這樣想那就大錯特錯了,其實此時synchronized對這塊資源不起任何作用。為什麼不起作用呢?我們來分析一下:

對於對象flag來說主要有兩個值true和false。但是true和false卻是兩個不同的常量對象,也就是說synchronized關鍵字其實鎖住的只是false對象,當下面test方法中把flag改為true就表示了另外一個對象。這就是為什麼synchronized關鍵字失效的原因。

如何去解決這個問題呢?這時候我們的AtomicBoolean類就可以出馬了,他可以很好的去解決這個問題。下面我們就來好好地分析一下AtomicBoolean類吧。

二、AtomicBoolean的使用

在一開始我們曾經也說到,在單線程中我們使用boolean是完全沒有問題的,我們看如下代碼:


一個java併發原子類AtomicBoolean解析

上面的代碼功能是這樣的,起床上班下班這三件事,一個人做完另外一個才可以繼續做。這種boolean情況,在單線程狀態下是安全的,但是在多線程條件下就是非線程安全的。我們可以創建兩個線程去測試一下:

一個java併發原子類AtomicBoolean解析

原本我們想的是起床上班下班這三件事,一個人完成另外一個人再做,但是通過運行結果我們會發現,並列執行了。怎麼才能實現我們的功能呢?我們再看下面的代碼:

一個java併發原子類AtomicBoolean解析

此時我們換成AtomicBoolean,在運行一下看看:

一個java併發原子類AtomicBoolean解析

我們會看到,此時執行的順序就確定了張無忌想進來卻進不來了。這就是其基本使用。下面我們分析一下其原理。

三、源碼分析

想要了解其原理我們就必須要到源碼中去看。在上面我們使用了compareAndSet方法,下面我們進入到這個方法中看看其源碼實現:

一個java併發原子類AtomicBoolean解析

這個compareAndSet源碼裡面調用了unsafe的compareAndSwapInt方法,也就是使用了CAS機制,舉一個我之前舉的例子,這裡expect和update是什麼意思呢?也就是說我們現在的boolean如果不是except那就不更新,如果是我們預期的except,那就更新,更新的值就是update。也就是CAS原理,我們通過例子解釋一下:

要給兒子訂婚,你預期的兒媳婦是西施,但是兒子找的女朋友是貂蟬,你一看不是你預期的西施(except),一氣之下就什麼也不做,如果是預期的西施,那就給他們訂婚。

注意:在這裡我們還會發現一個問題,那就是我們的Boolean其實轉化成了int類型,1表示true 0表示false。

這就是compareAndSet實現,底層使用的是CAS機制。當然還有很多其他的方法,我們可以看一下:

一個java併發原子類AtomicBoolean解析

​對於AtomicBoolean類其實是非常簡單的。也是java併發機制中比較簡單的類。這篇文章就先到這。如有問題還請指正。


分享到:


相關文章: