次のシグネチャを持つ静的メソッドがあります。
public static List<ResultObjects> processRequest(RequestObject req){
// process the request object and return the results.
}
上記のメソッドに対して同時に複数の呼び出しが行われるとどうなりますか?リクエストは同時に処理されますか、それとも次々に処理されますか?
あなたの質問に正確に答える:
同時アクセスが必要なオブジェクトを操作している場合は、synchronized
修飾子を追加する必要があります。
メソッドへのすべての呼び出しは同時に実行されます...しかし:
静的メソッドのコードが静的変数を変更するとすぐに、並行性の問題が発生する可能性があります(そしてスレッドセーフではない状況になります)。この場合、メソッドをsynchronized
として宣言できます。
メソッドがローカル変数のみを使用する場合、並行性の問題は発生しません。
同時実行を回避する必要がある場合は、明示的に同期する必要があります。メソッドが静的であるという事実は、それとは何の関係もありません。メソッド自体をsynchronized
として宣言すると、同期はクラスオブジェクトで行われます。それ以外の場合は、静的オブジェクトで同期する必要があります(静的メソッドにはthis
が存在しないため)。
あなたはそれを自分でチェックすることができます:
public class ConcurrentStatic {
public static void main(String[] args) {
for (String name: new String[] {"Foo", "Bar", "Baz"}) {
new Thread(getRunnable(name)).start();
}
}
public static Runnable getRunnable(final String name) {
return new Runnable() {
public void run() {
longTask(name);
}
};
}
public static void longTask(String label) {
System.out.println(label + ": start");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(label + ": end");
}
}
たくさんの答えがありますが、その理由を実際に指摘している人はいません。
だからこれはこのように考えることができます、
スレッドが作成されるたびに、それは独自のスタックで作成されます(作成時のスタックのサイズは約2MBだと思います)。したがって、実際に発生する実行は、このスレッドスタックのコンテキスト内で発生します。
作成された変数はすべてヒープに存在しますが、その参照はスタックに存在します。ただし、スレッドスタックに存在しない静的変数は例外です。
静的または非静的にかかわらず、実行する関数呼び出しは実際にはスレッドスタックにプッシュされます。完全なメソッドがスタックにプッシュされたため、行われる変数の作成はスタック内に存在し(静的変数は例外です)、1つのスレッドにのみアクセスできます。
したがって、すべてのメソッドは、静的変数の状態を変更するまでスレッドセーフです。
Javaの個別のスレッドからのすべてのメソッド呼び出しは、デフォルトで同時に行われます。