web-dev-qa-db-ja.com

Javaのスレッドセーフとは何ですか?

可能性のある複製:
スレッドセーフとはどういう意味ですか?

どのクラスもスレッドセーフであると非常に混乱しています。私は、クラスがスレッドセーフである場合、そのメソッドに特定の(同期された)ものがあることを理解しています。それは正しいか間違っていますか?その意味について詳しく説明してください。

50
Anuj

Sethが述べたように、スレッドセーフとは、問題が発生することなく、メソッドまたはクラスインスタンスを複数のスレッドで同時に使用できることを意味します。

次の方法を検討してください。

_private int myInt = 0;
public int AddOne()
{
    int tmp = myInt;
    tmp = tmp + 1;
    myInt = tmp;
    return tmp;
}
_

スレッドAとスレッドBは両方ともAddOne()を実行したいと考えています。ただし、Aは最初に開始され、myInt (0)の値をtmpに読み込みます。何らかの理由で、スケジューラはスレッドAを停止し、スレッドBに実行を延期することにしました。スレッドBは、myIntの値(まだ_0_)も独自の変数tmpに読み込むようになりました。スレッドBはメソッド全体を終了するため、最終的に_myInt = 1_になります。そして_1_が返されます。スレッドAの番です。スレッドAは続きます。そして、tmpに_1_を追加します(tmpは、スレッドAに対して_0_でした)。そして、この値をmyIntに保存します。 myIntは再び_1_です。

したがって、この場合、メソッドAddOne()が2回呼び出されましたが、メソッドがスレッドセーフな方法で実装されていないため、myIntの値は予想どおり_2_ではありません。ただし、_1_は、最初のスレッドが更新を完了する前に2番目のスレッドが変数myIntを読み取るためです。

スレッドセーフなメソッドの作成は、些細なケースでは非常に困難です。そして、かなりの数のテクニックがあります。 Javaでは、メソッドをsynchronizedとマークできます。これは、特定の時間に1つのスレッドのみがそのメソッドを実行できることを意味します。他のスレッドはインラインで待機します。メソッドスレッドセーフですが、メソッドで多くの作業が必要な場合、これは多くの時間を浪費します。別の手法は、メソッドのごく一部のみをマークすることですロックまたはセマフォを作成し、この小さな部分(通常はクリティカルセクションと呼ばれます)をロックすることにより、as synchronized()。ロックレススレッドセーフとして実装されるメソッドもあります。複数のスレッドが問題を引き起こすことなく同時に複数のスレッドをレースできるように構築されているため、メソッドが1つのアトミックコールのみを実行する場合がこれに該当します。一度に1スレッドずつ。

144
Roy T.

スレッドセーフとは、単に、問題を引き起こすことなく複数のスレッドから同時に使用できることを意味します。これは、任意のリソースへのアクセスが同期されることを意味する場合があります。

38
Seth Carnegie