${ 自分のための技術ナレッジ }

自分のための技術メモです

|Java| StreamAPI アトミックでない処理での注意

下記の処理は結果が実行毎に異なる。

parallel()により並列でラムダ式内の処理が実行されるが、インクリメント/デクリメントがアトミックで無いため足し引きのタイミングによって結果(p.x)が異なってしまう。

import java.util.stream.IntStream;

public class Test01 {

	public static void main(String[] args) {

		Person p1 = new Person();

		IntStream.range(0, 100000).parallel().forEach(i -> {
			if (i % 2 == 0) { p1.x++; } else { p1.x--;} ;
		});
		System.out.println(p1.x); // 結果がランダム

		Person p2 = new Person();
		IntStream.range(0, 100000).parallel().forEach(i -> {
			if (i % 2 == 0) { p2.inc(); } else { p2.dec();} ;
		});
		System.out.println(p2.x); // 結果は常にゼロ
	}

}

class Person {
	int x;

	synchronized void inc() {
		x++;
	}

	synchronized void dec() {
		x--;
	}
}