7

.NETのマルチスレッドに関するいくつかの初心者の質問は、私が吸収しようとしているいくつかの概念を強化するのに役立つと思います-私はいくつかのマルチスレッド資料(Albahari電子ブックを含む)を読みましたが、いくつかの質問の確認が必要だと感じていますこれらの概念を家に持ち帰るのを助けるために

  1. ロックスコープは、コードの共有領域を保護します-ループ内で単純な整数変数xをインクリメントするメソッドを実行するスレッドがあると仮定します-ただし、これは、別のスレッドの別のメソッドなど、変数xを変更する可能性のある他の場所のコードを保護しません..。。

    これは、同じ変数に影響を与える可能性のある2つの異なるコード領域であるため、変数xの周りの両方のロックスコープに同じロック変数を使用してコードの両方の領域をロックすることでこれを解決しますか?コードの両方の領域を異なるロック変数でロックした場合、これは変数を正しく保護しませんか?

  2. この例をさらに進めるために、同じロック変数を使用して、何らかの理由で、あるメソッドのコードが無限ループに入り、ロック変数を放棄しなかった場合はどうなりますか?他のメソッドのコードの2番目の領域はこれをどのように検出できますか?

  3. ロック変数の選択は、ロックの動作にどのように影響しますか?私はすでにこのテーマに関する多数の投稿を読んだことがありますが、決定的な答えを見つけることはできません-場合によっては、この目的のためにオブジェクト変数を明示的に使用する場合もあれば、lock(this)を使用する場合もあります。人々が型オブジェクトを使用するのを見てきました。

    ロック変数のさまざまな選択は、ロックの動作/範囲にどのように影響し、どのシナリオを使用するのが理にかなっていますか?

  4. add、remove、get、およびある種のCalculateメソッド(各オブジェクトが数量を表し、このメソッドが各値を合計するなど)を公開するクラスにラップされたハッシュテーブルがあり、これらのメソッドがすべてロックされているとします。ただし、オブジェクトへの参照が1回行われるとそのコレクションが他のコードで利用可能になり、アプリケーションに渡されると、このオブジェクト(ハッシュテーブルではない)は、そのクラスのメソッドを囲むロックスコープの外になります。次に、取得した実際のオブジェクトへのアクセス/更新を保護するにはどうすればよいですか。ハッシュテーブルから、Calculateメソッドに干渉する可能性がありますか?

これらの概念を強化するのに役立つヒューリスティックが提供されていることに感謝します-ありがとう!

4

2 に答える 2

2

1)はい

2)それは行き詰まりです

3)ブロックするコードの部分は、クラスの実装の詳細です。外部コードが同じオブジェクトをロックし、意図せずまたは悪意を持ってコードをブロックする可能性があるため、lock(this)またはを使用してロックオブジェクトを公開すると、問題が発生します。lock(this.GetType())ロックオブジェクトはプライベートである必要があります。

4)意味が明確ではありません。確かに、ハッシュテーブルを直接公開したくないでしょう。クラスのプライベートフィールドとして保持し、カプセル化します。

ただし、スレッドを使用してクラスをクライアントコードに安全に公開できる可能性は、公開するパブリックメソッドとプロパティの数に応じて非常に急速に低下します。クライアントコードだけが適切にロックできるようになるまですぐに到達します。きめ細かいロックは、クライアントコードがプロパティ値を保持しているときに、スレッド化の機会を多く生み出します。返すCountプロパティ値を言います。forループのように値を使用するまでに、Countプロパティが変更されている可能性があります。最も注意深い設計だけがこれらの罠、深刻な頭痛を避けることができます。

さらに、きめ細かいロックは、コードの最も内側の部分で必然的に行われるため、非常に非効率的です。ロックはそれほど高価ではなくおよそ100 cpuサイクルですが、すぐに加算されます。クラスオブジェクトが実際に複数のスレッドで使用されていない場合は、特に無駄な労力が必要です。

その場合、クラスをスレッドセーフでないと宣言する以外に選択肢はなく、クライアントコードはスレッドセーフな方法でそれを使用する必要があります。また、非常に多くの.NETクラスがスレッドセーフではない主な理由。これが、スレッディングを正しく行うのが非常に難しい最大の理由です。スレッディングを正しく行う可能性が最も低いプログラマーは、最も難しいことを行う責任があります。

于 2012-08-12T20:10:32.977 に答える
1

1)あなたは正しいです。たとえば変数xをインクリメントするコードの2つの異なる領域を保護するには、同じロックオブジェクトを使用する必要があります。

2)これはデッドロックと呼ばれ、マルチスレッドプログラミングの難しさの1つです。銀行家のアルゴリズムなど、デッドロックを防ぐために使用できるアルゴリズムがあります。

3)一部の言語では、ロックが簡単になります。たとえば、.Netでは、オブジェクトを作成して共有ロックとして使用できます。これは、特定のプロセス内でコードを同期するのに適しています。Lock(this)は、問題のオブジェクトにロックを適用するだけです。ただし、これを避けて、代わりにプライベートオブジェクトを作成して使用してください。Lock(this)は、デッドロック状態につながる可能性があります。下のロックオブジェクトは、おそらくクリティカルセクションの単なるラッパーです。異なるプロセス間でリソースを保護したい場合は、Mutexという名前のはるかに重いものが必要になります。これには、カーネルオブジェクトのロックが必要であり、コストがかかるため、必要な場合を除いて使用しないでください。

4)そこにもロックが適用されていることを確認する必要があります。しかし、確かに人々がこの参照でメソッドを呼び出すとき、彼らは同期を採用するメソッドを呼び出します。

于 2012-08-12T19:50:10.120 に答える