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
答案 0 :(得分:23)
绝对不线程安全。来自Queue<T>
的文档。
此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。不保证任何实例成员都是线程安全的。
只要未修改集合,
Queue<T>
可以同时支持多个阅读器。即便如此,通过集合枚举本质上不是一个线程安全的过程。为了在枚举期间保证线程安全,您可以在整个枚举期间锁定集合。要允许多个线程访问集合以进行读写,您必须实现自己的同步。
重读你的问题,你似乎对“这种类型的静态成员”这个短语感到困惑 - 它不是在谈论“静态队列”,因为没有这样的东西。对象不是静态的或不是 - 成员是。当谈到静态成员时,它正在谈论像Encoding.GetEncoding
这样的事情(Queue<T>
实际上没有任何静态成员)。实例成员是Enqueue
和Dequeue
之类的成员 - 与类型实例相关的成员而不是类型本身。
因此,您需要为每个操作使用锁定,或者如果您使用的是.NET 4,请使用ConcurrentQueue<T>
。
答案 1 :(得分:4)
答案 2 :(得分:2)
MSDN声明Queue的静态方法是线程安全的,而不是静态实例的实例方法是线程安全的。
答案 3 :(得分:1)
是的,您必须像MSDN所说的那样锁定
要允许多个线程访问集合以进行读写,您必须实现自己的同步。