3

一連の数字を生成するシングルトン IEnumerable があります。シーケンスは (基本的に無期限に) 相互利用可能であり、必要な場合にのみシーケンス内の次の番号を生成します。

public class Generator:IEnumerable<long> {

    private Generator() { }

    private static volatile Generator instance=new Generator();
    private static readonly object syncRoot=new object();
    public static Generator Instance { get { return instance; } }

    private static List<long> numsList=new List<long>();

    private void GenerateNextNumber() {
        long number;
        //Code to generate next number
        numsList.Add(number);
    }

    private long GenerateToNthNumber(int n) {
        lock(syncRoot) {
            while(numsList.Count<n)
                GenerateNextNumber();
        }
        return numsList[n-1];
    }

    public static long GetNthNumber(int n) {
        return Instance.GenerateToNthNumber(n);
    }

    private class GeneratorEnumerator:IEnumerator<long> {
        private int index=0;

        public long Current { get { return GetNthNumber(index); } }

        public void Dispose() { }

        object System.Collections.IEnumerator.Current { get { return GetNthNumber(index); } }

        public bool MoveNext() {
            index++;
            return true;
        }

        public void Reset() {
            index=0;
        }
    }

    public IEnumerator<long> GetEnumerator() {
        return new GeneratorEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}

このコードは、並行スレッドの数値を列挙して合計します。GenerateToNthNumber が呼び出されるたびにロックする必要がないようにする方法はありますか? 私はこのコードを試しました:

    private long GenerateToNthNumber(int n) {
        if(numsList.Count<n) {
            lock(syncRoot) {
                while(numsList.Count<n)
                    GenerateNextNumber();
            }
        }
        return numsList[n-1];
    }

しかし、複数の同時スレッドで数値を列挙して合計するテストを行うと、すべての結果が同じ合計になるわけではありません。私の目的は、要求されている数がすでに生成されている場合、それが可能であれば、ノンブロッキング読み取りを行うことです。これを行うより良い方法はありますか?

4

2 に答える 2

1

方法Listが実装されているため、別のスレッドで書き込まれている間、あるスレッドで安全に読み取ることはできません。代わりに、一度割り当てられると決して放棄されないネストされた既知のサイズの配列を使用することをお勧めします(たとえば、 を保持する配列が割り当てられるとtheList[15691]、アイテムは他の配列によって保持されることはありません)。このようなものは、アイテムを追加するときにロックを必要とする追加専用リストを実装するために簡単に使用できますが、ロックせずに読み取る場合は本質的にスレッドセーフです。

于 2013-01-18T19:26:02.737 に答える
0

スレッド セーフ コレクションの使用を考えたことはありますか?

http://msdn.microsoft.com/en-us/library/dd997305.aspx

于 2013-01-13T05:00:12.133 に答える