天天看點

Java建立線程安全的方法

原文連結 譯者:秦建平 校對:方騰飛

首先來看一個問題:

下面這個方法是線程安全的嗎?如何才能讓這個方法變成線程安全的?

<code>1</code>

<code>public</code> <code>class</code> <code>mycount {</code>

<code>2</code>

<code>  </code><code>private</code> <code>static</code> <code>int</code> <code>counter =</code><code>0</code><code>;</code>

<code>3</code>

<code>4</code>

<code>  </code><code>public</code> <code>static</code> <code>int</code> <code>getcount(){</code>

<code>5</code>

<code>    </code><code>return</code> <code>counter++;</code>

<code>6</code>

<code>  </code><code>}</code>

<code>7</code>

<code>}</code>

首先,這個方法不是線程安全的,因為counter++操作不是一個原子性的操作,也就意味着counter++操作包含了好幾個原子性的操作。實際上,counter++包含了三個原子性的操作,第一步是擷取counter的值,第二步是對counter的值加1,第三步是寫入的操作。在多線程環境對getcount()方法的調用,可能會出現下面的場景:

Java建立線程安全的方法

對這個方法增加同步的控制,會讓這個方法變成線程安全的。當給靜态方法添加synchronized關鍵字修飾的時候,實際上鎖定的是這個類所對應的class對象。在jvm中,一個類隻會存在一個class對象。

代碼示例如下:

<code>private</code> <code>static</code> <code>int</code> <code>counter =</code><code>0</code><code>;</code>

<code>public</code> <code>static</code> <code>synchronized</code> <code>int</code> <code>getcount(){</code>

<code>return</code> <code>counter++;</code>

如果這個方法不是靜态的,那麼給方法添加synchronized關鍵字修飾的時候,鎖住的實際上是相應的執行個體對象,而不是這個類所對應的class對象。

在這個特殊的計數器的例子當中,實際上隻要把counter++操作變成原子操作,就可以讓這個方法變成是線程安全的方法。在jdk5的線程庫,java.util.concurrent.atomic包中提供的atomicinteger類可以滿足我們的需求。

<code>private</code> <code>static</code> <code>atomicinteger counter =</code><code>new</code> <code>atomicinteger(</code><code>0</code><code>);</code>

<code>public</code> <code>static</code> <code>int</code> <code>getcount(){</code>

<code>return</code> <code>counter.getandincrement();</code>