Javaの++演算子はアトミックじゃない。つまり、++nは、n = n + 1と分解されたとき、nを読み込んだ後、1足した値をnに書き込む前に他のスレッドがnを変更していたら、すでに他のスレッドで行っていた変更が無効になる。
で、これはvolatileをつけてもだめ。
つまり、このプログラムの実行結果が20000にならない。
public class NonAtomicIncrement { static int count; public static void main(String[] args) throws InterruptedException{ Thread t = new Thread(){ @Override public void run(){ for(int i = 0; i < 10000; ++i){ ++count; } } }; t.start(); for(int i = 0; i < 10000; ++i){ ++count; } t.join(); System.out.println(count); } }
なので、synchronizedを使う必要があったのだけど、Java2SE 5.0からはAtomicIntegerなるものが用意されているので、これを使うと便利
import java.util.concurrent.atomic.AtomicInteger; public class AtomicIncrement { static AtomicInteger count = new AtomicInteger(); public static void main(String[] args) throws InterruptedException{ Thread t = new Thread(){ @Override public void run(){ for(int i = 0; i < 10000; ++i){ count.incrementAndGet(); } } }; t.start(); for(int i = 0; i < 10000; ++i){ count.incrementAndGet(); } t.join(); System.out.println(count); } }