43

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

ロックステートメント(C#リファレンス)

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

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

たとえば、データを保護するため、マルチスレッドアプリケーションでは意味があります。しかし、アプリケーションが他のスレッドをスピンオフしない場合は必要ですか?

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

どこでもロックを使用しているアプリケーションを継承しましたが、それはシングルスレッドであり、それらをそのままにしておくべきかどうか知りたいのですが、それらは必要ですか?

これは一般的な知識の質問であることに注意してください。アプリケーションの速度は良好です。これが将来従うべき優れたデザインパターンであるかどうか、または絶対に必要でない限りこれを避けるべきかどうかを知りたいです。

4

10 に答える 10

58

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

マルチスレッドコードの共有リソースを保護するには、ロックを使用する必要があります。他には何もありません。

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

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

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

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

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

すべてを意地悪にロックすることは、ひどいデザインパターンです。コードがランダムロックで雑然としていて、作業にバックグラウンドスレッドを使用することにした場合、デッドロックが発生する可能性があります。複数のスレッド間でリソースを共有するには注意深い設計が必要であり、トリッキーな部分を分離できるほど優れています。

于 2008-09-12T17:49:43.557 に答える
7

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

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

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

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

詳細については、 Thread.Abort() の危険性に関するこの記事を参照してください

于 2008-09-13T04:18:13.203 に答える
6

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

于 2008-09-12T17:52:37.933 に答える
2

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

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

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

マルチスレッドのパフォーマンスに関心がある場合は、 MSDNスレッドガイドラインから始めることをお勧めします。

于 2008-09-12T17:48:32.200 に答える
2

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

于 2008-09-12T17:41:23.497 に答える
1

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

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

于 2008-09-12T17:43:40.637 に答える
1

はい、ロックを使用するとパフォーマンスが低下しますが、一般的には問題にならないほど無視できます。

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

于 2008-09-12T17:44:15.630 に答える
1

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

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

于 2008-09-12T17:46:06.747 に答える
1

C# の「Mutex」に関する質問を参照してください。そして、'lock(Object)' ステートメントの使用に関するこれら 2 つの質問を具体的に見てください。

于 2008-09-12T20:08:25.860 に答える
0

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

于 2008-09-12T17:42:35.820 に答える