「スレッドセーフ」という用語の意味は何ですか?


367

2つのスレッドが同時に基礎となるデータを変更できないことを意味しますか?または、複数のスレッドがそのコードセグメントを実行しているときに、指定されたコードセグメントが予測可能な結果で実行されることを意味しますか?


8
ただ、この問題について、ここで興味深い議論を見ました:blogs.msdn.com/ericlippert/archive/2009/10/19/...
セバスチャン

回答:


256

ウィキペディアから:

スレッドセーフティは、マルチスレッドプログラムのコンテキストで適用可能なコンピュータープログラミングの概念です。複数のスレッドによる同時実行中に正しく機能するコードの一部は、スレッドセーフです。特に、複数のスレッドが同じ共有データにアクセスする必要性、および共有データの一部に常に1つのスレッドのみがアクセスする必要性を満たす必要があります。

スレッドセーフを実現するには、いくつかの方法があります。

再入:

あるタスクで部分的に実行され、別のタスクで再入力され、元のタスクから再開できるようにコードを記述する。これには、静的またはグローバル変数ではなく、通常はスタックにある、各タスクのローカル変数に状態情報を保存する必要があります。

相互排除:

共有データへのアクセスは、常に1つのスレッドのみが共有データを読み書きできるようにするメカニズムを使用してシリアル化されます。コードの一部が複数の共有データにアクセスする場合は、細心の注意が必要です。問題には、競合状態、デッドロック、ライブロック、飢餓、および多くのオペレーティングシステムの教科書で列挙されているその他のさまざまな問題が含まれます。

スレッドローカルストレージ:

変数はローカライズされているため、各スレッドには独自のプライベートコピーがあります。これらの変数は、サブルーチンやその他のコードの境界を越えて値を保持し、アクセスするコードが再入可能であっても、各スレッドに対してローカルであるため、スレッドセーフです。

原子操作:

共有データには、他のスレッドによって中断できないアトミック操作を使用してアクセスします。これには通常、ランタイムライブラリで利用可能な特別な機械語命令を使用する必要があります。操作はアトミックであるため、他のスレッドがアクセスするデータに関係なく、共有データは常に有効な状態に保たれます。アトミック操作は、多くのスレッドロックメカニズムの基礎を形成します。

続きを読む:

http://en.wikipedia.org/wiki/Thread_safety



4
このリンクには、技術的にはいくつかの重要なポイントがありません。問題の共有メモリは変更可能である必要があり(読み取り専用メモリはスレッドに対して安全ではありません)、複数のスレッドはa)メモリが不整合(誤っている)の途中でメモリに対して複数の書き込み操作を実行する必要があります。状態、およびb)メモリに不整合がある間、他のスレッドがそのスレッドに割り込むことができる
Charles Bretana、2012年

20
検索されたGoogleの最初の結果がwikiである場合、これを冗長にする意味はありません。
Ranvir、

「関数にアクセスするコード」とはどういう意味ですか?実行されている関数自体がコードですよね。
Koray Tugay

82

スレッドセーフコードは、多くのスレッドが同時にコードを実行している場合でも機能するコードです。

http://mindprod.com/jgloss/threadsafe.html


34
同じプロセス内で!
Ali Afshar

実際、同じプロセスで:)
Marek Blotny 2008年

4
「数週間安定して動作するコードを書くには、極端なパラノイアが必要です。」それは私が好きな引用です:)
ジムT

5
ああ!この答えは質問を再表明するだけです!---そして、なぜ同じプロセス内でのみ??? 複数のスレッドが異なるプロセスからコードを実行したときにコードが失敗した場合、間違いなく(「共有メモリ」はディスクファイルにある可能性があります)、スレッドセーフではありません。
Charles Bretana、2012年

1
@ mg30rg。おそらく、混乱は、コードのブロックが複数のプロセスによって実行されているが、プロセスごとに1つのスレッドによってのみ実行されている場合、どういうわけか、マルチスレッドのシナリオではなく、依然として「シングルスレッド」のシナリオであると考えた結果です。 。この考えは間違っていません。それは単に誤定義です。明らかに、複数のプロセスは、一般に(設計によってプロセスが互いにプロセス間OSを共有するスレッドと座標稀シナリオを除いて)、同期して同じスレッド上で実行されない
チャールズBretana

50

より有益な質問は、コードがスレッドセーフにならない理由です。答えは、真でなければならない4つの条件があるということです...次のコード(および機械語の翻訳)を想像してください

totalRequests = totalRequests + 1
MOV EAX, [totalRequests]   // load memory for tot Requests into register
INC EAX                    // update register
MOV [totalRequests], EAX   // store updated value back to memory
  1. 最初の条件は、複数のスレッドからアクセス可能なメモリ位置があることです。通常、これらの場所はグローバル/静的変数であるか、グローバル/静的変数から到達可能なヒープメモリです。各スレッドは、関数/メソッドスコープのローカル変数用に独自のスタックフレームを取得するため、これらのローカル関数/メソッド変数(スタック上)は、そのスタックを所有する1つのスレッドからのみアクセスできます。
  2. 2番目の条件は、これらの共有メモリの場所に関連付けられているプロパティ(多くの場合、不変と呼ばれます)が存在することです。これは、プログラムが正しく機能するためにtrueまたは有効でなければなりません。上記の例のプロパティは、「totalRequestsは、任意のスレッドがincrementステートメントの一部を実行した合計回数を正確に表す必要がある」ということです。通常、この不変のプロパティは、更新が正しく行われるために更新が行われる前にtrueを保持する必要があります(この場合、totalRequestsは正確なカウントを保持する必要があります)。
  3. 3番目の条件は、実際の更新の一部の間、不変のプロパティが保持されないことです。(処理の一部で一時的に無効またはfalseになります)。この特定のケースでは、totalRequestsがフェッチされてから更新された値が格納されるまで、totalRequestsは不変条件を満たしませ
  4. 発生する(およびコードをしたがってためにレースのために行われなければならない第四の最終的な条件NOT「スレッドセーフ」である)は、別のスレッドが共有メモリにアクセスすることができなければならないということであるながら、それによって矛盾を生じさせる又は、不変が壊れています不正な動作。

6
これは、データ競合と呼ばれるものだけを対象としており、もちろん重要です。しかし、コードがスレッドセーフにならない方法は他にもあります。たとえば、デッドロックにつながる可能性のある悪いロックです。System.exit()をJavaスレッドのどこかで呼び出すような単純なものでさえ、そのコードはスレッドセーフではありません。
2013

2
これはある程度意味論だと思いますが、デッドロックを引き起こす可能性のある不正なロックコードによってコードが安全でなくなることはないと私は主張します。まず、上記のような競合状態が発生しない限り、最初からコードをロックする必要はありません。次に、デッドロックを引き起こすような方法でロックコードを記述した場合、それはスレッドセーフではなく、単に悪いコードです。
Charles Bretana 2013

1
ただし、デッドロックはシングルスレッドの実行時には発生しないので、ほとんどの場合、これは「スレッドセーフではない」という直感的な意味に確実に該当します。
Jon Coombs、2014

もちろん、マルチスレッドを実行していないとデッドロックは発生しませんが、1台のマシンで実行している場合はネットワークの問題が発生しないと言っているようなものです。プログラマが更新を完了する前に重要なコード行から抜け出し、他のサブルーチンで変数を変更するようにコードを記述した場合、他の問題もシングルスレッドで発生する可能性があります。
Charles Bretana、2016

34

私はブライアン・ゲッツの包括的なJava並行性の定義が包括的であることを気に入っています

「ランタイム環境によるそれらのスレッドの実行のスケジューリングやインターリーブに関係なく、複数のスレッドからアクセスされたときにクラスが正しく動作する場合、クラスはスレッドセーフであり、呼び出しコードの追加の同期やその他の調整は必要ありません。 」


この定義は不完全で具体的ではなく、包括的ではありません。安全に実行する必要がある回数は1回だけですか?十回?毎回?時間の80%ですか?そして、それが「安全でない」とするものを特定していません。安全に実行できませんでしたが、ゼロ除算エラーが原因で失敗した場合、それはスレッド「安全でない」になりますか?
Charles Bretana

次回はより市民的になり、話し合うことができます。これはRedditではなく、私は失礼な人々と話す気分ではありません。
Buu Nguyen

他人の定義についてのあなた自身への侮辱としてのあなたの解釈のコメントは伝えています。感情的に反応する前に、内容を読んで理解する必要があります。私のコメントについて何ら邪悪なことはありません。私はその定義の意味について指摘していました。私がポイントを説明するために使用した例があなたを不快にさせたら、申し訳ありません。
Charles Bretana

28

他の人が指摘したように、スレッドセーフとは、1つのコードが複数のスレッドで一度に使用された場合、エラーなしで機能することを意味します。

これは、コンピュータの時間とより複雑なコーディングを犠牲にして行われることもあるため、常に望ましいとは限りません。クラスが1つのスレッドでのみ安全に使用できる場合は、そうする方がよい場合があります。

たとえば、Javaには、ほぼ同等の2つのクラスがStringBufferありStringBuilderます。違いは、StringBufferスレッドセーフであるため、の単一のインスタンスをStringBuffer複数のスレッドで一度に使用できることです。StringBuilderはスレッドセーフではなく、Stringが1つのスレッドのみで構築されている場合(大多数)の場合のより高性能な代替品として設計されています。


22

スレッドセーフコードは、異なるスレッドによって同時に入力された場合でも、指定どおりに機能します。これは、多くの場合、中断することなく実行する必要のある内部データ構造または操作が、さまざまな変更から同時に保護されることを意味します。


21

それを理解するより簡単な方法は、コードをスレッドセーフではないものにすることです。スレッド化されたアプリケーションに望ましくない動作をさせる2つの主な問題があります。

  • ロックせずに共有変数にアクセスする
    この変数は、関数の実行中に別のスレッドによって変更される可能性があります。関数の動作を確実にするために、ロックメカニズムを使用してそれを防止する必要があります。一般的な経験則は、可能な限り最短の時間でロックを維持することです。

  • シェア変数への相互依存によるデッドロック
    2つのシェア変数AとBがある場合。1つの関数では、最初にAをロックしてから、後でBをロックします。別の関数では、Bをロックし始め、しばらくしてからAをロックします。 2番目の関数がAのロック解除を待機するときに最初の関数がBのロック解除を待機する潜在的なデッドロックです。この問題はおそらく開発環境では発生せず、時々発生するだけです。これを回避するには、すべてのロックを常に同じ順序にする必要があります。


9

はいといいえ。

スレッドセーフティは、共有データに一度に1つのスレッドのみがアクセスすることを確認するだけではありません。共有データへのシーケンシャルアクセスを確保すると同時に、競合状態デッドロックライブロックリソース不足を回避する必要があります。ます。

複数のスレッドが実行されている場合の予期しない結果は、スレッドセーフコードの必須条件ではありませんが、多くの場合副産物です。たとえば、共有キュー、1つのプロデューサースレッド、およびいくつかのコンシューマースレッドを使用してプロデューサー/コンシューマースキームを設定すると、データフローは完全に予測可能になる場合があります。より多くの消費者を紹介し始めると、よりランダムに見える結果が表示されます。


9

本質的に、マルチスレッド環境では多くのことがうまくいかない可能性があります(命令の並べ替え、部分的に構築されたオブジェクト、CPUレベルでのキャッシュのために異なるスレッドで同じ値を持つ同じ変数など)。

私はJava Concurrency in Practiceで与えられた定義が好きです:

[コードの一部]は、ランタイム環境によるそれらのスレッドの実行のスケジューリングやインターリーブに関係なく、複数のスレッドからアクセスされたときに正しく動作し、追加の同期やその他の調整がない場合、スレッドセーフです。呼び出しコード。

することで、正しく彼らはプログラムがその仕様に準拠した動作することを意味します。

考案された例

カウンターを実装するとします。次の場合、正しく動作すると言えます。

  • counter.next() 以前にすでに返された値を決して返さない(簡単にするために、オーバーフローなどは想定していない)
  • 0から現在の値までのすべての値が、ある段階で返されました(値はスキップされません)

スレッドセーフカウンターは、同時にアクセスするスレッドの数に関係なく、これらのルールに従って動作します(通常、単純な実装の場合はそうではありません)。

注:プログラマーへのクロスポスト



5

スレッドの安全性と確定性を混同しないでください。スレッドセーフコードは、非決定的である場合もあります。スレッド化されたコードでの問題のデバッグが困難であることを考えると、これはおそらく通常のケースです。:-)

スレッドセーフティは、スレッドが共有データを変更または読み取るときに、他のスレッドがデータを変更する方法でそれにアクセスできないようにするだけです。コードが正確さのために実行の特定の順序に依存している場合、これを確実にするには、スレッドセーフティに必要なもの以外の同期メカニズムが必要です。


5

他の良い答えの上にいくつかの情報を追加したいと思います。

スレッドセーフとは、複数のスレッドがメモリの不整合エラーなしに同じオブジェクトでデータを読み書きできることを意味します。高度にマルチスレッド化されたプログラムでは、スレッドセーフプログラムは共有データに副作用を引き起こしません

詳細については、このSEの質問をご覧ください。

スレッドセーフとはどういう意味ですか?

スレッドセーフプログラムは、メモリの一貫性を保証します

高度なコンカレントAPIに関するOracleのドキュメントページから:

メモリの一貫性のプロパティ:

Java™言語仕様の第17章では、共有変数の読み取りや書き込みなどのメモリ操作に関するハプネスビフォアリレーションを定義しています。1つのスレッドによる書き込みの結果は、読み取り操作の前に書き込み操作が発生した場合にのみ、別のスレッドによる読み取りで認識されることが保証されます。

synchronized及びvolatile構築物だけでなく、Thread.start()およびThread.join()方法、缶フォームは事前発生します関係。

java.util.concurrentとそのサブパッケージのすべてのクラスのメソッドは、これらの保証をより高いレベルの同期に拡張します特に:

  1. オブジェクトを並行コレクションに配置する前のスレッドのアクションは、別のスレッドのコレクションからその要素にアクセスまたは削除した後のアクションの前に発生します。
  2. 前の提出にスレッド内のアクションRunnableExecutor起こる-前にその実行が開始されます。同様に、に送信された呼び出し可能オブジェクトExecutorService
  3. 別のスレッドでFuture結果を取得した後の前に発生するアクションによって表される非同期計算によって実行されるアクションFuture.get()
  4. 別のスレッドの同じシンクロナイザーオブジェクト上など、成功した「取得」メソッドに続く発生前アクションなど、シンクロナイザーメソッドを「解放」するLock.unlock, Semaphore.release, and CountDownLatch.countDown前のアクションLock.lock, Semaphore.acquire, Condition.await, and CountDownLatch.await
  5. を介してオブジェクトを正常に交換したスレッドのペアごとExchangerに、exchange()、各スレッドでのは、別のスレッドでの対応するexchange()の後の発生します。
  6. 呼び出し前のアクションCyclicBarrier.awaitおよびPhaser.awaitAdvance(およびそのバリアントと同様に)バリアアクションによって実行されるビフォアビフォアアクション、およびバリアアクションによって実行されるアクションは、他のスレッドでの対応する待機からの戻りに成功した後のビフォアビフォアアクションです。

4

他の回答を完了するには:

メソッドのコードが次の2つのうちの1つを実行する場合にのみ、同期が問題になります。

  1. スレッドセーフではない外部リソースで動作します。
  2. 永続オブジェクトまたはクラスフィールドの読み取りまたは変更

つまり、メソッド内で定義された変数は常にスレッドセーフです。メソッドへのすべての呼び出しには、これらの変数の独自のバージョンがあります。メソッドが別のスレッドまたは同じスレッドによって呼び出された場合、またはメソッドがそれ自体を呼び出した場合(再帰)でも、これらの変数の値は共有されません。

スレッドのスケジューリングは、ラウンドロビンであることが保証されていません。タスクは、同じ優先度のスレッドを犠牲にして、CPUを完全に占有する場合があります。Thread.yield()を使用して良心を持つことができます。(Javaで)Thread.setPriority(Thread.NORM_PRIORITY-1)を使用してスレッドの優先順位を下げることができます

さらに、次のことに注意してください。

  • これらの「スレッドセーフ」構造を反復処理するアプリケーションでの実行時の大きなコスト(すでに他の人が言及している)。
  • Thread.sleep(5000)は5秒間スリープすることになっています。ただし、誰かがシステムの時刻を変更すると、非常に長い間、またはまったく眠れないことがあります。OSはウェイクアップ時間を相対形式ではなく絶対形式で記録します。

2

はい、はい。これは、データが複数のスレッドによって同時に変更されないことを意味します。ただし、プログラムは基本的にそうでなくても、期待どおりに動作し、スレッドセーフに見える場合があります。

結果の予測不能性は、データが予期されたものとは異なる順序で変更される結果となる「競合状態」の結果であることに注意してください。


2

例でこれに答えましょう:

class NonThreadSafe {

    private int counter = 0;

    public boolean countTo10() {
        count = count + 1;
        return (count == 10);
    }

このcountTo10メソッドは、カウンターに1を追加し、カウントが10に達した場合にtrueを返します。trueは1回だけ返す必要があります。

これは、1つのスレッドのみがコードを実行している限り機能します。2つのスレッドが同時にコードを実行すると、さまざまな問題が発生する可能性があります。

たとえば、countが9で始まる場合、1つのスレッドがcountに1を追加(10にする)できますが、最初のスレッドが10との比較を実行する前に、2番目のスレッドがメソッドに入り、もう一度1を追加(11にする)できます。その後、両方のスレッドが比較を行い、countが11であり、どちらもtrueを返さないことがわかります。

したがって、このコードはスレッドセーフではありません。

本質的に、すべてのマルチスレッドの問題は、この種の問題のバリエーションによって引き起こされます。

解決策は、加算と比較を分離できないようにすることです(たとえば、2つのステートメントをある種の同期コードで囲むことによって)、または2つの操作を必要としない解決策を考案することによって。このようなコードはスレッドセーフです。


1

少なくともC ++では、スレッドセーフは、名前から多くの部分が除外されているという点で、少し誤った名称であると考えています。スレッドセーフになるためには、コードは通常、プロアクティブでなければなりません。それは一般的に受動的な品質ではありません。

クラスをトレッドセーフにするには、オーバーヘッドを追加する「追加」機能が必要です。これらの機能は、クラスの実装の一部であり、一般的に言えば、インターフェースから隠されています。つまり、別のスレッドは、別のスレッドによる同時アクセスと競合することを心配する必要なく、クラスのメンバーのいずれかにアクセスできます。また、実行する必要なく、非常に遅延した方法で、プレーンな古い通常の人間のコーディングスタイルを使用できます。呼び出されているコードの根幹にすでに組み込まれているすべてのクレイジーな同期のこと。

そして、これが一部の人々が内部的に同期されたという用語を使うことを好む理由です。

用語セット

私が遭遇したこれらのアイデアには、3つの主要な用語セットがあります。最初の、そして歴史的にもっと人気のある(しかし悪い)は:

  1. スレッドセーフ
  2. スレッドセーフではない

2番目(およびそれ以上)は次のとおりです。

  1. スレッドプルーフ
  2. スレッド互換
  3. 敵対的なスレッド

3番目は次のとおりです。

  1. 内部同期
  2. 外部同期
  3. 同期できない

アナロジー

スレッドセーフスレッドプルーフ内部同期

内部で同期(別名。スレッドセーフまたはスレッドの証明)システムは、ホストがドアであなたを迎えて、そして自分自身をキューイングから禁止しますがレストランです。ホストは、複数の顧客に対応するためのレストランのメカニズムの一部であり、パーティーの規模や彼らが持っているように見える時間を考慮に入れるなど、待っている顧客の座席を最適化するためにいくつかのトリッキーなトリックを使用できます、または電話でのご予約も承っております。これはすべて、レストランと対話するためのインターフェースの一部であるため、レストランは内部で同期されています。

スレッドセーフではありません(ただし便利です)〜スレッド互換性があります外部同期されますフリースレッド

銀行に行くとしましょう。行、すなわち銀行の出納係の競合があります。あなたは野蛮人ではないので、リソースの競合の最中に行うには、文明化された存在のように列を作ることが最善であると認識しています。技術的にこれを行う人は誰もいません。私たちはあなたが自分でそれを行うために必要なソーシャルプログラミングを持っていると思います。この意味で、銀行のロビーは外部で同期されています。スレッドセーフではないと言えるでしょうか。これが、スレッドセーフスレッドアンセーフのバイポーラ用語セットを使用する場合の意味です。それは非常に良い用語のセットではありません。より良い用語は外部的に同期され、銀行のロビーは複数の顧客からのアクセスに敵対的ではありませんが、顧客を同期する作業も行いません。顧客自身がそれを行います。

これは「フリースレッド」とも呼ばれ、「フリー」は「シラミから解放」の場合と同じです。この場合、ロックです。より正確には、同期プリミティブ。これは、コードがそれらのプリミティブなしで複数のスレッドで実行できることを意味しません。それはそれらが既にインストールされていないことを意味するだけであり、あなたが自分でインストールするかどうかは、コードのユーザーであるあなた次第です。独自の同期プリミティブをインストールすることは難しい場合があり、コードをよく考える必要がありますが、今日のハイパースレッドCPUでのプログラムの実行方法をカスタマイズできるため、プログラムを可能な限り最速にすることもできます。

スレッドセーフではない(そして悪い)〜スレッドに敵対的非同期

スレッド敵対的なシステムの日常の例えは、スポーツカーがウインカーの使用を拒否し、車線を自由に変更することです。それらの運転スタイルは、それらと調整する方法がないため、スレッドに敵対的または非同期です。これにより、解決策なしに同じ車線の競合が発生し、2台の車がプロトコルを使用せずに同じスペースを占有しようとする事故が発生する可能性があります。これを防ぐ。このパターンは、より広く反社会的であると考えることもできます。これは、スレッドに固有ではなく、プログラミングの多くの領域に一般的に適用できるためです。

なぜ、スレッドセーフら。悪い用語セットです

最初と最も古い用語セットでは、スレッドの敵意スレッドの互換性をより細かく区別できません。スレッドの互換性は、いわゆるスレッドセーフティよりパッシブですが、呼び出されたコードがスレッドの同時使用に対して安全ではないという意味ではありません。これは、内部の実装の一部として提供するのではなく、これを可能にする同期について受動的であることを意味し、呼び出し元のコードにそれを延期します。スレッド互換性は、ほとんどの場合、デフォルトでコードがおそらく記述される方法ですが、悲しいことに、これは、本質的にアンチセーフティであるかのように、スレッドセーフでないと誤って考えられることが多く、プログラマにとって混乱の主なポイントです。

注:多くのソフトウェアマニュアルでは、「スレッドセーフ」という用語を実際に使用して「スレッド互換」を表しているため、すでに混乱していたものにさらに混乱が生じています。この理由のために、「スレッドセーフ」と「スレッドアンセーフ」という用語は絶対に避けます。同意できないために「スレッドセーフ」と呼ぶソースもあれば、「スレッドアンセーフ」と呼ぶソースもあるからです。安全性に関するいくつかの追加基準(同期プリミティブ)を満たさなければならないのか、それとも単に「安全」と見なされるために敵対的であってはならないのかについて。したがって、これらの用語を避け、代わりにより賢明な用語を使用して、他のエンジニアとの危険な誤解を回避してください。

目標を思い出させる

基本的に、私たちの目標はカオスを破壊することです。

私たちは、信頼できる確定的システムを作成することでそれを実現します。決定論は高価であり、主に並列性の喪失、パイプライン処理、および並べ替えの機会費用が原因です。私たちは、コストを低く抑えるために必要な決定論の量を最小限に抑える一方で、私たちが提供できる小さな決定論をさらに浸食するような決定をすることを避けます。

スレッドの同期とは、順序を増やしてカオスを減らすことです。これを行うレベルは、上記の条件に対応しています。最高レベルとは、システムが毎回完全に予測可能な方法で動作することを意味します。2番目のレベルは、システムが十分に動作して、呼び出しコードが予測不能性を確実に検出できることを意味します。たとえば、条件変数での誤ったウェイクアップや、準備ができていないためのミューテックスのロックの失敗などです。3番目のレベルは、システムが他の誰かと遊ぶのに十分な動作をせず、混乱を招かずにシングルスレッドでのみ実行できることを意味します。


1

代わりの思考のコードクラススレッドセーフかどうかなど、私はそれを考えることがより有用であると考え行動スレッドセーフであることなど。2つのアクションは、任意のスレッドコンテキストから実行されたときに指定どおりに動作する場合、スレッドセーフです。多くの場合、クラスはアクションのいくつかの組み合わせをスレッドセーフな方法でサポートし、他の組み合わせはサポートしません。

たとえば、配列リストやハッシュセットなどの多くのコレクションは、最初に1つのスレッドで排他的にアクセスされ、他のスレッドから参照が見えるようになった後は変更されない場合、任意の組み合わせで任意の方法で読み取られることを保証します干渉のない糸の。

さらに興味深いことに、.NETの元の非ジェネリックコレクションなどの一部のハッシュセットコレクションは、アイテムが削除されない限り、1つのスレッドのみがそれらに書き込みを行うという保証を提供します。コレクションを読み取ると、更新が遅延して任意の順序で発生する可能性があるコレクションにアクセスするかのように動作しますが、それ以外の場合は正常に動作します。スレッド#1がXを追加してからYを追加し、スレッド#2がYを検索してからXを検索する場合、スレッド#2はYは存在するがXは存在しないことを確認できます。そのような動作が「スレッドセーフ」であるかどうかは、スレッド#2がその可能性に対処する準備ができているかどうかに依存します。

最後の注記として、一部のクラス(特に通信ライブラリのブロック)には、他のすべてのメソッドに対してスレッドセーフである「close」または「Dispose」メソッドがありますが、スレッドセーフである他のメソッドはありません。お互い。スレッドがブロック読み取り要求を実行し、プログラムのユーザーが[キャンセル]をクリックした場合、読み取りを実行しようとしているスレッドが閉じる要求を発行する方法はありません。ただし、クローズ/破棄要求は非同期でフラグを設定する可能性があり、これにより読み取り要求ができるだけ早く取り消されます。いずれかのスレッドでcloseが実行されると、オブジェクトは役に立たなくなり、以降のアクションでのすべての試行はすぐに失敗します。


0

簡単に言うと、コードブロックで複数のスレッドを実行しても安全であれば、スレッドセーフです*。

*条件が適用されます

条件は、1などの他の回答で言及されています。1つのスレッドまたは複数のスレッドを実行しても、結果は同じになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.