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