web-dev-qa-db-ja.com

javaのマルチスレッド環境での静的メソッドの動作

私を悩ませ、心の中でいくつかの議論をする単純な愚かな質問があります。以下の質問についての疑問をすべて捨てたいです。

class Clstest{

    public static String testStaticMethod(String inFileStr) {

        // section 0

        // section 1

        // do something with inFileStr

        // section 2

        // section 3

        return inFileStr;

    }

}

5つのスレッドがそれぞれClstest.testStaticMethod("arg-n")の呼び出しを同時に実行していると仮定しましょう。

スレッド1はClstest.testStaticMethod("arg-1")を呼び出します。

スレッド1がセクション1にある場合、スレッド2はClstest.testStaticMethod("arg-2")を呼び出します。

それでは、スレッド1はどうなりますか?スリープ状態になりますか?

スレッド1がチャンスを得たとき、一時停止されたセクション1から実行を再開しますか?

1つのClstest.testStaticMethodがあり、同じClstest.testStaticMethodが5つのスレッドすべてで共有されている場合、どうなりますか?

複数のスレッドによって送信されたinFileStrを交換する可能性はありますか?

109
namalfernandolk

ハンス・パッサントの答えは良いです。しかし、これに出くわしてJavaに不慣れな人には、もう少し単純なレベルで説明しようと思った。ここに行きます。

Javaのメモリは、ヒープとスタックの2種類に分けられます。ヒープはすべてのオブジェクトが存在する場所であり、スタックはスレッドが作業を行う場所です。各スレッドには独自のスタックがあり、他のスタックにアクセスできません。各スレッドには、現在実行中のコードのビットを指すコードへのポインターもあります。

スレッドが新しいメソッドの実行を開始すると、そのメソッドの引数とローカル変数を独自のスタックに保存します。これらの値の一部は、ヒープ上のオブジェクトへのポインターである場合があります。 2つのスレッドが同じメソッドを同時に実行している場合、両方のスレッドはそのメソッドを指すコードポインターを持ち、スタック上に引数とローカル変数の独自のコピーを持ちます。スタック上のものがヒープ上の同じオブジェクトを指している場合にのみ、互いに干渉します。その場合、あらゆる種類のことが起こります。しかし、Hansが指摘しているように、文字列は不変(変更不可)であるため、これが「共有」されている唯一のオブジェクトであれば安全です。

多くのスレッドが同じメソッドを実行できます。 JVMはJavaスレッドをハードウェアスレッドにスケジュールされているOSスレッドにマップするため、マシン上にあるコアの数に依存します。したがって、複雑な同期メカニズムを使用せずに、これらのスレッドがインターリーブする方法をほとんど制御できません。

スリープは、スレッドがそれ自体に対して行うことです。

186
selig

スリープ状態になりますか?

いいえ、スレッドを実行しても、意図的に相互に同期しない限り、他のスレッドには影響しません。複数のプロセッサコアを使用している場合、最近のすべてのマシンがそうであるように、それらのスレッドはまったく同時に実行される可能性があります。マシンに十分なコアがない可能性があるため、5つのスレッドを開始すると、この可能性は少し低くなります。オペレーティングシステムはそれらを選択せざるを得ず、実行するたびに時間がかかります。スレッドスケジューラのジョブ。その場合、スレッドは「スリープ」状態ではなく、単に一時停止され、スレッドスケジューラが実行する機会を与えるのを待っています。スケジューラーによって中断された場所から再開します。

複数のスレッドによって送信されたinFileStrを交換する可能性はありますか?

そのような可能性はありません。スレッドには独自のスタックがあるため、メソッドの引数とローカル変数はスレッドごとに一意になります。さらに、stringを使用すると、文字列は不変であるため、これらのスレッドが互いに干渉することはありません。

引数が別の種類の可変オブジェクトへの参照である場合、そのような保証はありません。または、メソッド自体が静的な変数またはヒープ上のオブジェクトへの参照を使用する場合。スレッドがオブジェクトを変更し、別のスレッドがそれを読み取る場合、同期が必要です。 C#言語のlockキーワードは、このような必要な同期を実装する定型的な方法です。メソッドがstaticであるという事実は、そのような同期が必要ないという意味ではありません。スレッドが同じオブジェクトにアクセスすることを心配する必要がないため(thisを共有する)、あまりありません。

64
Hans Passant