質問: サーバー上のアプリケーション内に、あるクラスの静的変数の値を更新するAPIを実装したとします。 このAPIに不特定多数のユーザが接続した際の挙動に関して質問です。 例えば以下の2つのクラスを考えます(Javaで書いてます)。 ``` public class SampleClass { public static int x; public static void sampleMethod() { x += 1; } } ``` ``` public class SampleClass2 { public int sampleMethod2() { SampleClass.sampleMethod(); return SampleClass.x; } } ``` API内ではこの`sampleMethod2()`を1回呼び出し、その戻り値がAPIのレスポンスとして手元に渡ってくる想定です。 このAPIをA, Bという別のユーザが、各々に呼びだしたときにそれぞれが得られた値の組み合わせを(A, B)と表現するとします。 **質問内容は、(2,2)の組み合わせが得られる可能性というのはあるのかどうか、ということです。** 私の理解は以下のとおりです。 1. AがAPIを呼びだした後に、アプリケーションが終了する前にBがAPIを呼びだした場合:(1,2) 2. AがAPIを呼びだした後にアプリケーションが終了、その後Bがアプリケーション起動&APIを呼びだした場合:(1,1) 3. A, Bがほぼ同時でAPIを呼び出し、それぞれの処理が非同期的に進行し、Aの`SampleClass.sampleMethod()`の次にBの`SampleClass.sampleMethod()`が実行された場合:(2,2) 以上の理解は正しいでしょうか。 更新対象が静的変数ではなく、例えばDBの同じレコードだった場合、最初の更新時にレコードがロックされる為3のような状態は起きないと思っていますが、静的変数だった場合はどうなるのかと思い質問した次第です。 また、もし3の状態がありえない場合、それはAの処理が完了した後にBの処理が確実に実行されるような機構が存在すると考えられますが、それにはどのようなものがあるのでしょうか。キーワードだけでも教えていただけると助かります。 **※Javaに限らずお聞きしたいです。** 以上、よろしくお願いします。
回答: 普通に2,2あり得ますね。だって、インクリメントと値取得を別にやっているんですから。 A⇒インクリメント、B⇒インクリメント A返却、B返却は十分にあり得ます。(メソッドと参照が一緒になっていても、同じことはおこります。) Javaであれば値更新から返却までを1つのメソッドに閉じ込め、synchronized 指定してやればいいのでは?と考えます。 あ、そもそもこういう風に大域変数でずーーーっと持ち続けることの是非は別途検討しておくべきですよね。事故の元ですし。。ステートレスに作ったほうが取り回しやすいですよね。 普通に考えて、プロセスの中に値を閉じ込めておくと、受け手の水平スケーラビリティを確保できなくなるので、アクセス数にあわせて水平にスケールするのが常套手段なAPIの世界で、この実装は致命的かなぁ~と考えたりします。(スケールしたときにプロセスごとに値が変わりますから。。) 仮に「ここだけはダイジョブ。影響ないから」とか考えていたとして、そういうのが1つでもあると、結局スケールするときに、全体調査が走ったりするので、面倒なだけですよね。と