正确锁定线程安全的自生成列表(c#)

本文关键字:列表 锁定 线程 安全 | 更新日期: 2023-09-27 17:50:55

我有一个单例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];
    }

但是当测试在多个并发线程中枚举和求和数字时,并不是所有的结果最终都是相同的和。我的目标是有非阻塞读取,如果被要求的数字已经生成,如果这是可能的。有更好的方法吗?

正确锁定线程安全的自生成列表(c#)

List的实现方式,当它在另一个线程中写入时,它不能安全地在一个线程中读取。我建议你使用嵌套的已知大小的数组,一旦分配,就永远不会放弃(例如,一旦分配了一个数组,它将保存theList[15691],该项目将永远不会被任何其他数组持有)。这样的东西可以很容易地用来实现一个只添加列表,它在添加项时需要锁,但本质上是线程安全的,可以在没有锁的情况下读取。

您考虑过使用线程安全的集合吗?

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