2

以下のコードは機能しているように見えます。つまり、外側のリストに増分整数のサブリストを入力します。

私はただラッキーですか?

「スロット」を事前に割り当て、クロスオーバーしないように注意しています。

class Program
{
    static List<List<int>> allLists;

    static void Main(string[] args)
    {
        allLists = new List<List<int>>(553);

        for (int i = 0; i < 553; i++)
        {
            allLists.Insert(i, new List<int>());
        }

        Enumerable.Range(0, 552).AsParallel().ForAll((i) => InsertRange(i));
    }

    static void InsertRange(int index)
    {
        allLists[index] = Enumerable.Range(0, 7205).ToList();
    }
}

あるリストが別のリストを破棄する危険はありますか?

4

3 に答える 3

1

配列のさまざまな部分に並列にアクセスすることは、.Netではスレッドセーフです。また、List<T>は配列に支えられているため、コードもスレッドセーフである必要があると思います。

しかし、私はあなたが物事を複雑にしすぎていると思います。PLINQを使用してすべての内部リストを生成してから、を使用ToArray()して最終的な配列を作成できます(またはToList()、本当に作成したい場合はList<T>)。PLINQには独自のバージョンのRange()and ToArray()(およびToList())があるため、これもより効率的であると思います。

だから、私はあなたのコードを次のように書き直します:

allLists = ParallelEnumerable.Range(0, 552)
    .AsOrdered()
    .Select(i => Enumerable.Range(0, 7205).ToList())
    .ToArray();

もちろん、これはすべて、内部リストの作成を並列化することで実際にコードが高速化される場合にのみ意味がありますが、それを自分で測定する必要があります。

于 2012-09-06T20:46:46.867 に答える
1

はい、InsertRange メソッド内でロックする必要があります。ただし、要素の作成がまだ並行して行われていることを確認してください。

private static Object settingValue = new Object();
static void InsertRange(int index)
{
    // This part can be executed in parallel.
    List<int> values = Enumerable.Range(0, 7205).ToList();

    lock (settingValue)
    {
        allLists[index] = values;
    }
}

編集:リストの作成にはかなりの時間がかかり、インデックス番号への参照を割り当てると、一方の割り当てが他方の割り当てと完全に重複する可能性が低いため、幸運である可能性があります。

于 2012-09-06T12:17:27.247 に答える
0

PLINQ の潜在的な落とし穴によると、潜在的なスレッドセーフでないメソッド InsertRange(int index) を持つことができます

于 2012-09-06T12:09:50.097 に答える