10

.NET 4.0では、System.Collections.Concurrent名前空間が導入されました。

System.Collections.Concurrent名前空間は、複数のスレッドがコレクションに同時にアクセスしている場合は常に、 System.Collectionsおよび System.Collections.Generic名前空間の対応するタイプの代わりに使用する必要があるいくつかのスレッドセーフなコレクションクラスを提供します。」

SynchronizedCollection<T>クラス(.NET 3.0以降で使用可能):

「ジェネリックパラメーターで要素として指定されたタイプのオブジェクトを含むスレッドセーフなコレクションを提供します」

...System.Collections.Generic名前空間にあります。

では、なぜSynchronizedCollection<T>クラスはスレッドセーフであるのに並行ではないのでしょうか。

SynchronizedCollection<T>ジェネリッククラスが他のコレクションとは異なり、コレクションと互換性がない理由は何System.Collections.Concurrentですか?

更新:System.Collections.Concurrent質問を言い換えさせてください:名前空間に 属するすべてのジェネリックコレクションの共通の分母と特徴的な新機能は何ですか?SynchronizedCollection<T>ジェネリッククラスには存在しません(使用中は不可能です) ?

タイトルを「.NET3.0System.Collections.Concurrentに追加された.NET4.0コレクションとはSynchronizedCollection?」に変更しました。 しかし、ほとんどの場合、.NET3.0に基づいて実行できなくなった理由を知りたいと思っています。

Update2:メモについて:

「この質問にはすでに答えがあるかもしれません:

SynchronizedCollectionと他の同時コレクションの違いは何ですか?「」

答えは私の質問の文脈では混乱しています-新機能は進化的(.NET 4.0以前の機能を使用)ですか、それとも革新的(.NET 4.0以前では利用できません)ですか?

4

3 に答える 3

9

以前のスレッドセーフコレクションクラスにはかなり大きな欠陥があり、スレッドセーフな方法で繰り返すことはできません。反復は一般にスレッドセーフにするのが非常に困難です。コードがコレクションを反復しているにコレクションに追加またはコレクションから削除されるアイテムを認識するイテレーターを使用するコードを作成するクリーンな方法はありません。本当に安全な唯一の方法は、反復が行われている間、コレクションへのアクセスをロックすることです。これは非常に望ましくありません。このようなロックは通常、非常に長い間保持されます。次善の方法は、コレクションのコピーを作成することです。これは、変更されないため、いつでも安全に繰り返すことができます。そのソリューションのO(n)ストレージ要件を好む人は誰もいません。

.NET 1.0コレクションクラスのSynchronized()メソッドは特に厄介でした。Microsoftは、反復がスレッドセーフではないことを秘密にしませんでした。彼らは事故を検出するためのコードさえ追加しました、それはスレッドがコレクションを変更したときに例外をスローします。ただし、この例外は十分な頻度で発生することはなく、警告ラベルの読み取りに失敗し、何をしてもスレッドセーフなコレクションが確実に安全であると思い込んでいる.NETプログラマーは戸惑います。もちろん、コレクションの最も基本的な操作がスレッドセーフではない場合に、コレクションを「スレッドセーフ」と呼ぶことは問題ではありませんでした。Microsoftが意味したのは、「スレッドを使用してもコレクションが破損しないため、スレッドセーフである」ということでした。プログラマーが読むもの「スレッドセーフ」でした。Microsoftは、.NET2.0ジェネリックコレクションクラスで同じ間違いを繰り返しませんでした。

これは.NET4で対処され、新しいコレクションを繰り返しても例外はスローされません。それ以外の場合は、古いデータを読み取っているため、コードの誤動作を防ぐために何もしません。それはあなたが自分で解決しなければならない解決できない問題です。

于 2013-02-27T12:14:18.203 に答える
6

.NET 4.0の主な焦点は、同時実行性でした。Microsoftは.NET4.0でSystem.Threading.Tasks名前空間を導入したため、System.Collections.Concurrent名前空間も追加することは理にかなっています。の場所で述べたように、System.Collections.Concurrentのコレクションは、ロックのない方法で実装されるため、パフォーマンスが高くなります。これは簡単な作業ではありません。これが、Microsoftが.NET3.xの更新ではなく新しいメジャー.NETリリースに属していると感じた理由だと思います。ロックフリーの動作は、特に.NET4.0の新機能であるInterlocked.CompareExchangeの汎用バージョンを使用して実装されています。

System.Collections.Concurrentのクラスを実装する方法に興味がある場合は、.NET4.0のリリース前に彼が書いたJoeDuffyの本「ConcurrentProgrammingonWindows」を読むことをお勧めします。この本は、いくつかの並行コレクションがどのように実装されているかを示しています。

于 2013-02-27T11:07:56.877 に答える
1

リンクされた複製は、質問の「新機能」の部分に答えます。私はここでこのメモについて話します:

それが.NET3.0に基づいて行うことを不可能にしたのは何ですか

私の推測では、それを不可能にしたものは何もありません。.NET 4.0で新しいクラスの逆コンパイルを取得し、(必要に応じて構文を変更して).NET 3.5に対してそのようなクラスを自分で作成すると、完全に機能すると思います。

Enumerable.Zipこれは、たとえば、.NET 4.0が使用できない場合に、.NET3.5で手動で実装する方法と同じです。確かに、.NET 2.0に対するLINQのようなライブラリの実装をどこかで見たのを覚えています(もちろん、C#言語機能はありません!)。

一般に、.NETでは、ライブラリが新しいCLR機能に依存していない限り、以前のバージョンに対してライブラリが再実装されるのを止めることはできません。この状況の注目すべき例の1つは、ジェネリックスです。.NET2.0より前は、CodeSmithなどのcodegenツールを使用して、異なるクラスをそれぞれ手動でクランクすることなく、タイプセーフなコレクションのサポートを取得する方法はありませでし

では、.NET 3.5にクラスが存在することを妨げるものが何もないのならConcurrent、なぜMicrosoftはそれらを作成しなかったのでしょうか。単に時間と予算-出荷は機能であり、一部の機能はそれよりも重要ではないため、後のバージョンまで待たなければなりません。

于 2013-02-27T10:06:55.847 に答える