web-dev-qa-db-ja.com

静的クラス変数を変更しない場合、非同期静的メソッドはスレッドセーフですか?

not同期された静的メソッドがあるかどうか疑問に思っていましたが、not静的変数はスレッドセーフですか?メソッドがその内部にローカル変数を作成する場合はどうでしょうか?たとえば、次のコードはスレッドセーフですか?

public static String[] makeStringArray( String a, String b ){
    return new String[]{ a, b };
}

そのため、このメソッドを連続して同時に呼び出す2つのスレッドがある場合、1つは犬(「グレートデーン」と「ブルドッグ」)、もう1つは猫(「ペルシャ」と「シャム」)になります。同じ配列に?または、猫と犬が同時にメソッドの同じ呼び出し内にいることはありませんか?

143
Tobogganski

このメソッドは100%スレッドセーフであり、staticでなくても可能です。スレッド間でデータを共有する必要がある場合、スレッドセーフの問題が発生します。原子性、可視性などに注意する必要があります。

このメソッドは、スタックに常駐するパラメーターおよびヒープ上の不変オブジェクトへの参照でのみ動作します。 スタックは本質的にスレッドに対してローカルなので、データの共有は一切発生しません。

不変オブジェクト(この場合はString)もスレッドセーフです。作成されたオブジェクトは変更できず、すべてのスレッドが同じ値を参照するためです。一方、メソッドが(可変)Dateを受け入れていた場合、問題が発生した可能性があります。 2つのスレッドが同じオブジェクトインスタンスを同時に変更し、競合状態と可視性の問題を引き起こす可能性があります。

207

メソッドは、何らかの共有状態を変更する場合にのみスレッドセーフではありません。静的かどうかは関係ありません。

28
Konrad Garus

この関数は完全にスレッドセーフです。

あなたがそれについて考える場合...これが異なっていたらどうなるかを仮定してくださいすべての通常の関数は、同期されていないとスレッドの問題が発生するため、複数のスレッドから呼び出される可能性があるため、JDKのすべてのAPI関数を同期する必要があります。また、ほとんどの場合、アプリは何らかのAPIを使用しているため、マルチスレッドアプリは事実上不可能です。

これについて考えるにはあまりにもばかげているので、あなただけのために:問題がある可能性のある明確な理由がある場合、メソッドはスレッドセーフではありません。私の関数に複数のスレッドがある場合、そしてステップデバッガーがあり、最初の...次のスレッド...次のスレッド...問題がありますか?見つかった場合、スレッドセーフではありません。

また、ConcurrentHashMapなどの記載されているクラスを除き、ほとんどのJava 1.5 Collectionクラスはスレッドセーフではないことにも注意してください。

本当にこれに飛び込みたいのであれば、volatileキーワードとそのすべての副作用をよく見てください。 Java.util.ConcurrentのSemaphore()およびLock()クラス、およびそれらの友人を見てください。クラスに関するすべてのAPIドキュメントを読んでください。学び、満足することも価値があります。

この非常に手の込んだ回答で申し訳ありません。

12
Daniel

同期された静的メソッドでstaticキーワードを使用して、スレッド間で共有される静的データを変更します。 staticキーワードを使用すると、作成されたすべてのスレッドがメソッドの単一バージョンを求めて競合します。

同期インスタンスメソッドと共にvolatileキーワードを使用すると、各スレッドが共有データの独自のコピーを持ち、スレッド間で読み取り/書き込みがリークしないことが保証されます。

1
clinton

不変の文字列オブジェクトは、上記のスレッドセーフシナリオのもう1つの理由です。代わりに、可変オブジェクトが使用されている場合(makeMutableArray ..など)、スレッドセーフは確実に壊れます。

0
harsh