問題タブ [readerwriterlockslim]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - ReaderWriterLockSlim を使用した Parallel.ForEach のデッドロック
アプリケーションのデッドロックに関する興味深い問題があります。ReaderWriterLockSlim を使用して読み取りと書き込みを同期するインメモリ データ ストアがあります。読み取りメソッドの 1 つは、Parallel.ForEach を使用して、一連のフィルターを指定してストアを検索します。フィルターの 1 つが同じストアの一定時間の読み取りを必要とする可能性があります。デッドロックが発生するシナリオは次のとおりです。
更新:以下のコード例。
実際のメソッド呼び出しで更新されたstore
ステップConcreteStoreThatExtendsGenericStore
- スレッド1 はストアで読み取りロックを取得します -
store.Search(someCriteria)
- スレッド 2は、書き込みロックでストアを更新しようとします - -、スレッド 1
store.Update()
の後ろのブロック - Thread1はストアに対して Parallel.ForEach を実行し、一連のフィルターを実行します。
- Thread3 ( Thread1の Parallel.ForEach によって生成される) は、ストアの一定時間の読み取りを試みます。読み取りロックを取得しようとしますが、Thread2の書き込みロックの背後でブロックされます。
- Thread1はThread3に参加できないため、終了できません。 Thread2はThread1の背後でブロックされているため、終了できません。
理想的には、現在のスレッドの祖先スレッドが既に同じロックを持っている場合、読み取りロックを取得しようとしないことです。これを行う方法はありますか?または、別の/より良いアプローチがありますか?
c# - この ReaderWriterLockSlim ロック パターンは正しく見えますか?
私はReaderWriterLockSlimを使用して読み取り/書き込みを同期してきましたが、これまでのところ非常にうまく機能しています。
オブジェクトのコレクションがあり、読み取り/書き込みロックはDictionary<string, ReaderWriterLockSlim>
. 複数の読み取りロックをアトミックに取得する必要があるシナリオがあります。1 つのスレッドが同時に複数の書き込みロックを保持しようとするようなコードを持っていないことは確かです。そのため、以下のコードは問題なく動作すると思います。
読み取りロックではなく書き込みロックを使用して以下のアプローチを試みた場合、ロックが常に同じ順序で発生することを保証できない限り、デッドロックが発生することはほぼ確実です (私の場合はできません)。
次のことを前提として、このコードに問題がある人はいますか?
- 他の場所では、書き込みロックを保持しているスレッドは、他のロック (読み取りまたは書き込み) を保持できません。
- 複数のスレッドが任意の数の読み取りロックを同時に保持できます
何かご意見は?
c# - 更新または削除できる共有メモリのスレッドセーフな列挙
ファイルの状態情報を保持するために使用されるスレッド間で共有オブジェクトがあります。情報を保持するオブジェクトは次のクラスです。
}
私はこの辞書を次のように呼んでいます。SynchronizedDictionary_cache=new SynchronizedDictionary();
他のスレッドを生成して、次のようにスレッドを使用できます。_cache ["key"];
辞書は実行時に変更できます。ここでは問題ありません。それとも私は間違っていますか?私の目には、コレクションを反復処理する列挙子を作成したいので、問題は列挙子にあります。どうすればよいですか?私はこれらの3つの解決策を考えました:
- 次のような列挙子を作成します:http: //www.codeproject.com/Articles/56575/Thread-safe-enumeration-in-C (ただし、ReaderWriterLockSlimを使用)
- SyncRootと同様に(ただしReaderWriterLockSlimを使用して)ロックオブジェクトを公開し、呼び出し元がenterメソッドとexit読み取りメソッドを呼び出すようにします。
- 代わりに、情報を保持するデータベース(SQLite fx)を使用してください。
番号1)の問題は次のとおりです。
- コンストラクターを使用して読み取りモードに入ります。GetEnumerator()がforeachを使用せずに手動で呼び出された場合はどうなりますか?そして、disposeを呼び出すのを忘れてください。
- これが良いコーディングスタイルかどうかはわかりません。私はコードが好きですが。
- 呼び出し元がforeachを使用している場合、列挙子のインスタンス化と破棄の呼び出しの間に呼び出し元が何をする可能性があるのかわかりません。私が正しく読んだドキュメントを理解していれば、重い作業をしているリーダーが1人残っている限り、これはライターをブロックしてしまう可能性があります。
2)の問題は次のとおりです。
- 私はこれを公開するのが好きではありません。.NET APIがそれを行うことは知っていますが、好きではありません。
- 適切に出入りするのは発信者次第です
3)目は問題ありません。しかし、私はこの小さなプロジェクトを空き時間プロジェクトとして行っており、マルチスレッドとリフレクションについてもっと学びたいので、これを最後のオプションとして残しておきたいと思います。実行時にコレクションを反復処理する理由は、いくつかの基準に一致する値を見つけたいからです。
たぶん、問題を発明したのは私だけですか?
ConcurrentDictionaryを知っていますが、これは使いたくありません。私はこのプロジェクトを遊び場として使っています。糸脱毛と反射で遊ぶ。
編集
読み書きをしているのは何なのかと聞かれました。そして、私はこの編集でこれを伝えるつもりです。私はこのクラスを読んだり書いたりしています:
私はたくさんの読み取りを行っていますが、実行時の書き込みはほとんどありません。多分私は2000年と1回の書き込みを行います。たくさんのオブジェクトもありません、多分200。
c# - 再帰を回避するためのC#ReaderWriterLockSlimのベストプラクティス
変更する要素を取得するためにreadメソッドとreadメソッドを使用するwriteメソッドでReaderWriterLockSlimを使用するクラスがあります。簡単な例は次のとおりです。
上記のように、このコードは、読み取りロックに入ろうとしたときに書き込みロックがすでに保持されているため、LockRecursionException
呼び出し時にをスローします。ChangeFoo()
GetFoo()
ドキュメントを確認しました。これReaderWriterLockSlim
を使用LockRecursionPolicy.SupportsRecursion
して、上記を機能させることができます。ただし、ドキュメントでは、これを新しい開発には使用せず、既存のコードをアップグレードする場合にのみ使用することも推奨しています。
これを考えると、書き込みメソッドが読み取り専用メソッドを使用して変更が必要なものを取得できるという同じ結果を達成するためのベストプラクティスは何ですか?
c# - ReaderWriterLockSlim のエラー
この例外が発生しまし
た 読み取りロックが保持されずに解放されています。
System.Threading.ReaderWriterLockSlim.ExitReadLock() で ..GetBreed(String)
以下は、ロックにアクセスするコード内の唯一の場所です。ご覧のとおり、再帰はありません。この例外がどのように発生するのか理解できません。
multithreading - より高速な TMultiReadExclusiveWriteSynchronizer?
そこにもっと速い種類はTMultiReadExclusiveWriteSynchronizer
ありますか?おそらくFastCode?
Windows Vista 以降、Microsoft はSlim Reader/Writer lockを追加しました。Delphiよりもはるかに優れたパフォーマンスを発揮しますTMultiReadExclusiveWriteSynchronizer
。残念ながら、これは Windows Vista 以降にしか存在せず、実際にまだほとんどのユーザーが持っていません。
おそらく、内部で使用されている概念はSlim Reader/Writer lock
、ネイティブの Delphi コードでやり直すことができますが、それを行った人はいますか?
TMultiReadExclusiveWriteSynchronizer
(競合がない場合でも、単一のスレッドで)ロックを取得および解放すると、 100%のオーバーヘッドが発生する(操作時間が2倍になる)状況があります。ロックせずに実行できますが、クラスはスレッドセーフではなくなります。
より速いものはありますTMultiReadExclusiveWriteSynchronizer
か?
注: i を使用するとTCriticalSection
、2% のパフォーマンス ヒットしか発生しません (ただし、取得が成功した場合、つまりシングル スレッドで競合がない場合、クリティカル セクションは高速であることが知られています)。CS の欠点は、「複数のリーダー」機能を失うことです。
測定
内部とTMultiReadExclusiveWriteSynchronizer
内部でかなりの時間を費やしています。BeginRead
EndRead
次に、Windows 独自のSlimReaderWriter Lockを使用するようにコードを移植し(再帰的なロックの取得をサポートしていないため、一部のコードを書き換えます)、結果をプロファイリングしました。
TMultiReadExclusiveWriteSynchronizer
: 反復ごと
に 10,698 ns 1,000,000 回反復するには 10,697,772,613 nsSRWLock
: 反復ごとに 8,802 ns
1,000,000 回反復するには 8,801,678,339 nsOmni Reader-Writer lock
: 反復ごとに 8,941 ns
1,000,000 回反復するには 8,940,552,487 ns
SRWLocks (別名 Omni の回転ロック) を使用すると 17% の改善。
現在、まだ Windows XP を使用している企業全体が存在するため、Windows Vista SRWLocksを使用するようにコードを永続的に切り替えることはできません。
スリムロックは、InterlockedCompareExchange
機能を慎重に使用するだけです。しかし、私がうまく使用できるよりも慎重です。関係する 140 の機械語命令を盗むには程遠いです。
ボーナスリーディング
c# - ReaderWriterLockSlim の所有者を知るには?
マルチスレッドを多用するアプリケーションを書いています。一部のスレッドは、ReaderWriterLockSlim を使用して observablecollection を共有します。
私は時々デッドロックを抱えており、デッドロックの瞬間にロックを保持しているスレッドを知る必要があります。どうすればこれを知ることができますか? オブジェクトのプロパティを調べましたが、明らかなものは何もありませんでした。現在、私が知っているのは、どのスレッドがロックを待っているかだけです。
ご協力いただきありがとうございます!
編集:もちろん、デバッグ時にすべてのデバッグ情報を利用できるようにすることについて話している。
c# - ReaderWriterLockSlim を IDisposable ハンドラーにラップする
全て、
IDisposable パターンを使用して ReaderWriterLockSlim ロックを制御することは、私にとって非常に自然なことのように思えます。この一般的な (らしい) タスクを処理する BCL には何もないことに気付きました。以下のコードは本当にナイーブなのでしょうか? この一般的な領域に関連する SO に関する他の質問がいくつか見られますが、このアイデアの適切性に正面から取り組むものはありません。
問題は、ReaderWriterLockSlim オブジェクトの Dispose() メソッドを呼び出す必要があるかどうかではなく、ラッパーだけです。
使用法:
c# - ReaderWriterLockSlimとダブルロックチェックパターン
編集:私がすでに得た答えから、私が提示した最初の解決策は、実際には「読み取りをブロックしない」ではないことを理解しています。これは、読み取りが解放される前に1つのスレッドのみがアップグレード可能なロックに入ることができ、書き込みロックを取得できないためです...
だから私の質問、存在しない場合は作成で「読み取りをブロックしない」という最初の解決策を正しい方法で作成するにはどうすればよいですか?
マルチスレッド読み取りをブロックしないための2つの解決策を理解しようとしています。以下の2つのソリューションの違いは何ですか(まだいくつかのことを理解していないかもしれませんが、試しています):
私の場合、これらのソリューションはどちらも、非ブロッキング読み取りを実行し、書き込み時にのみブロッキングを実行できます...もしそうなら、どのような利点がありReaderWriterLockSlim
ますか?私がグーグルで見つけたように、Monitor
はよりはるかに速いですReaderWriterLockSlim
。もちろん、読んでいるときに辞書の状態が間違ってしまう可能性があることは理解していますが、私にとっては問題ありません。
ありがとう
c# - 読者に有利なReaderWriterLockSlimに相当するものはありますか?
私はしばらくの間ReaderWriterLockSlimを使用してきましたが、これまでのニーズを満たしています。ReaderWriterLockSlim
アプリケーションを微調整し続けると、それは私のユースケースには少し最適では ないことがわかります。
ドキュメント(および私の経験)によれば、それはリーダーよりもライターを優先します(つまり、リーダーとライターがキューに入れられている場合、ライターが優先されます)。ただし、読者に有利な同等のものが必要です。そのようなコンポーネントの副作用(特に、ライターの枯渇の問題)を理解しています。
誰かが指摘できる本番環境に対応したものはありますか?ありがとう。