这是否使用静态队列线程安全?

时间:2010-10-06 08:31:49

标签: c# .net thread-safety

msdn文档声明静态通用队列是线程安全的。这是否意味着以下代码是线程安全的?换句话说,当一个线程将一个int排队并且另一个线程同时使一个int出局时是否存在问题?我是否必须为线程安全锁定Enqueue和Dequeue操作?

class Test {
    public static Queue<int> queue = new Queue<int>(10000);

    Thread putIntThread;
    Thread takeIntThread;

    public Test() {
        for(int i = 0; i < 5000; ++i) {
            queue.Enqueue(0);
        }
        putIntThread = new Thread(this.PutInt);
        takeIntThread = new Thread(this.TakeInt);
        putIntThread.Start();
        takeIntThread.Start();
    }

    void PutInt() {
        while(true)
        {
            if(queue.Count < 10000) {//no need to lock here as only itself can change this condition
                queue.Enqueue(0);
            }
        }
    }

    void TakeInt() {
        while(true) {
            if(queue.Count > 0) {//no need to lock here as only itself can change this condition
                queue.Dequeue();
            }
        }
    }

}

编辑:我必须使用.NET 3.5

4 个答案:

答案 0 :(得分:23)

绝对线程安全。来自Queue<T>的文档。

  

此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。不保证任何实例成员都是线程安全的。

     

只要未修改集合,Queue<T>可以同时支持多个阅读器。即便如此,通过集合枚举本质上不是一个线程安全的过程。为了在枚举期间保证线程安全,您可以在整个枚举期间锁定集合。要允许多个线程访问集合以进行读写,您必须实现自己的同步。

重读你的问题,你似乎对“这种类型的静态成员”这个短语感到困惑 - 它不是在谈论“静态队列”,因为没有这样的东西。对象不是静态的或不是 - 成员是。当谈到静态成员时,它正在谈论像Encoding.GetEncoding这样的事情(Queue<T>实际上没有任何静态成员)。实例成员是EnqueueDequeue之类的成员 - 与类型实例相关的成员而不是类型本身。

因此,您需要为每个操作使用锁定,或者如果您使用的是.NET 4,请使用ConcurrentQueue<T>

答案 1 :(得分:4)

答案 2 :(得分:2)

MSDN声明Queue的静态方法是线程安全的,而不是静态实例的实例方法是线程安全的。

答案 3 :(得分:1)

是的,您必须像MSDN所说的那样锁定

  

要允许多个线程访问集合以进行读写,您必须实现自己的同步。