質問

MSDN のロック キーワードの主な機能を理解しました

lock ステートメント (C# リファレンス)

ロックキーワードは、特定のオブジェクトの相互排除ロックを取得し、ステートメントを実行してからロックを解放することにより、ステートメントブロックを重要なセクションとしてマークします。

ロックはいつ使用する必要がありますか?

たとえば、マルチスレッド アプリケーションではデータが保護されるため、これは理にかなっています。しかし、アプリケーションが他のスレッドをスピンオフしない場合、それは必要でしょうか?

ロックの使用にパフォーマンスの問題はありますか?

あらゆる場所でロックを使用しているアプリケーションを継承したところですが、それはシングルスレッドなので、ロックを残しておいた方がよいのか、そもそもロックは必要なのでしょうか?

これは一般的な知識に関する質問であることに注意してください。アプリケーションの速度は問題ありません。これが将来従うべき良い設計パターンなのか、それとも絶対に必要な場合を除き、これを避けるべきなのかを知りたいのです。

役に立ちましたか?

解決

ロックはいつ使用する必要がありますか?

マルチスレッド コードで共有リソースを保護するには、ロックを使用する必要があります。それ以外の目的ではありません。

しかし、アプリケーションが他のスレッドをスピンオフしない場合、それは必要でしょうか?

絶対違う。それはただの時間の無駄です。ただし、システム スレッドを暗黙的に使用していないことを確認してください。たとえば、非同期 I/O を使用する場合、元のスレッドではなく、ランダムなスレッドからコールバックを受信する可能性があります。

ロックの使用にパフォーマンスの問題はありますか?

はい。シングルスレッド アプリケーションではそれほど大きくありませんが、なぜ必要のない呼び出しを行うのでしょうか?

...それが将来従うべき良いデザインパターンであれば[?]

すべてを勝手にロックするのはひどい設計パターンです。コードがランダムなロックで乱雑になっている場合に、何らかの作業にバックグラウンド スレッドを使用することにした場合、デッドロックが発生する可能性があります。複数のスレッド間でリソースを共有するには慎重な設計が必要であり、扱いにくい部分を分離できればできるほど良いでしょう。

他のヒント

ここでの答えはすべて正しいようです。ロックの有用性は、スレッドがロックされたコードに同時にアクセスすることをブロックすることです。ただし、この分野には多くの微妙な点があり、その 1 つは、ロックされたコード ブロックが自動的にマークされることです。 クリティカル領域 共通言語ランタイムによる。

コードがクリティカルとしてマークされると、領域全体を完全に実行できない場合、ランタイムはアプリケーション ドメイン全体が潜在的に危険にさらされているとみなして、メモリからアンロードする可能性があります。引用するには MSDN:

たとえば、ロックを保持したままメモリを割り当てようとするタスクを考えてみましょう。メモリ割り当てに失敗した場合、ドメイン内に同じロックを待機している他のタスクが存在する可能性があるため、現在のタスクを中止するだけでは AppDomain の安定性を確保するのに十分ではありません。現在のタスクが終了すると、他のタスクがデッドロックになる可能性があります。

したがって、アプリケーションがシングルスレッドであっても、これは危険である可能性があります。ロックされたブロック内の 1 つのメソッドが例外をスローし、その例外が最終的にブロック内で処理されなくなると考えてください。例外がコール スタックを通じて発生するときに処理されたとしても、コードの重要な領域は正常に終了しませんでした。CLR がどのように反応するかは誰にも分かりません。

詳細については、こちらをお読みください Thread.Abort() の危険性に関するこの記事.

アプリケーションが思ったほどシングルスレッドではない理由があるかもしれないことに留意してください。たとえば、さまざまなタイマー クラスの一部 (ただし、Windows フォーム タイマーではありません) と同様に、.NET の非同期 I/O はプール スレッドでコールバックする可能性があります。

一般的に、アプリケーションがシングルスレッドの場合、lock ステートメントはあまり活用されません。あなたのアプリケーションを正確に知らないので、それらが役立つかどうかはわかりませんが、おそらくそうではないと思います。さらに、アプリケーションがあらゆる場所でロックを使用している場合、マルチスレッド環境で動作することにそれほど自信を持てるかどうかはわかりません - 元の開発者はそうでしたか 実は マルチスレッド コードの開発方法を知っているのでしょうか、それとも、それでうまくいくだろうという漠然とした期待から、ロック ステートメントをあらゆる場所に追加しただけなのでしょうか?

ロックは、共有状態、他のスレッドによって同時に変更される状態を変更するコードの周囲で使用する必要があり、それらの他のトレッドは同じロックを取得する必要があります。

ロックは実際にはメモリ アクセス シリアライザであり、(ロックを取得する) スレッドは現在のスレッドがロックから出るまでロックが入るのを待つため、メモリ アクセスはシリアル化されます。

質問に答えると、シングルスレッドアプリケーションではロックは必要ありませんが、パフォーマンスに副作用があります。C# のロックはカーネル同期オブジェクトに基づいており、ロックを取得するたびにユーザー モードからカーネル モードへの移行が作成されるためです。

マルチスレッドのパフォーマンスに興味がある場合は、以下から始めるとよいでしょう。 MSDN スレッドのガイドライン

あなた できる 変数のロックにはパフォーマンスの問題がありますが、通常は、「ロックされた」コード ブロック内で費やす時間を最小限に抑えるようにコードを構築します。

ロックを解除するところまでは。それはコードが正確に何をしているかによって異なります。シングルスレッドであっても、オブジェクトがシングルトンとして実装されている場合、複数のクライアントがそのインスタンス (メモリ内、サーバー上) を同時に使用する可能性があります。

はい、ロックを使用するとパフォーマンスに多少のペナルティが発生しますが、通常は無視できる程度であり、問​​題になりません。

ロック (またはその他の相互排他ステートメントや構成) の使用は、通常、複数のスレッド (独自に作成したスレッドまたは呼び出し元のスレッド) がオブジェクトと対話して、基礎となる状態や状態を変更する機会があるマルチスレッド シナリオでのみ必要になります。データが維持されています。たとえば、複数のスレッドからアクセスできるコレクションがある場合、別のスレッドが項目を読み取ろうとしている間に、あるスレッドが項目を削除してそのコレクションの内容を変更することは望ましくありません。

Lock(token) は、複数のスレッドで同時に実行すべきではない 1 つ以上のコード ブロックをマークするためにのみ使用されます。アプリケーションがシングルスレッドの場合、存在し得ない状況から保護されます。

また、ロックによってパフォーマンスが低下するため、コードが実行される前に同時アクセスをチェックする命令が追加されます。必要な場合にのみ使用してください。

を参照してください。 質問 C#の「ミューテックス」について。そして見てください これら 特に「lock(Object)」ステートメントの使用に関する質問。

スレッドが 1 つしかない場合、アプリ内にロックを設定する意味はありません。確かに、パフォーマンス ヒットになりますが、そのヒットが積み重なって重要なものになるまでにはかなりの数の呼び出しが必要です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top