Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Queue.Count是线程安全的吗?_C# - Fatal编程技术网

C# Queue.Count是线程安全的吗?

C# Queue.Count是线程安全的吗?,c#,C#,我需要一个线程来修改队列(添加和删除元素),另一个线程只调用Queue.Count。它是安全的还是我需要使用锁或ConcurrentQueue?队列不提供线程安全保证,因此您确实需要您提到的两种选择之一 此类型的公共静态(在Visual Basic中共享)成员是线程 安全的。任何实例成员都不能保证线程安全 一个队列(T)可以同时支持多个读卡器,只要 集合未被修改。即使如此,通过集合枚举 本质上不是线程安全过程。保线 枚举期间的安全性,您可以在 整个枚举。允许多个用户访问集合的步骤 对于读写线程,

我需要一个线程来修改队列(添加和删除元素),另一个线程只调用
Queue.Count
。它是安全的还是我需要使用
ConcurrentQueue

队列
不提供线程安全保证,因此您确实需要您提到的两种选择之一

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

一个队列(T)可以同时支持多个读卡器,只要 集合未被修改。即使如此,通过集合枚举 本质上不是线程安全过程。保线 枚举期间的安全性,您可以在 整个枚举。允许多个用户访问集合的步骤 对于读写线程,您必须实现自己的线程 同步

线程安全性标题下的队列:

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

为了保证队列的线程安全,所有操作都必须 通过同步方法返回的包装器完成

通过集合枚举本质上不是线程安全的 程序即使在同步集合时,其他线程也可以 仍然修改集合,这会导致枚举数抛出 例外。要保证枚举期间的线程安全,可以 在整个枚举过程中锁定集合或捕获 由其他线程所做的更改导致的异常

msdn有相当好的文档。我建议您下次再查看。

根据文档,队列属性不是线程安全的

但是它是一个原子int,最糟糕的情况是你读取了错误的(过时的)值。这可能是个问题,也可能不是


但是,由于您必须采取措施防止读取线程缓存该值,因此您最好
lock()

它不能保证线程安全

Count
的当前实现是线程安全的。这不太可能改变,但没有承诺

大多数时候,这不是很有用。若您正在做一些类似于将当前大小估计值输出到UI的事情,那个么这是完全安全的。如果您据此做出任何决定,则不安全:

if(queue.Count != 0)
  return queue.Dequeue; //not thread-safe as Dequeue isn't threadsafe.

if(queue.Count != 0)
{
  lock(queue)
    return queue.Dequeue; //not thread-safe, won't corrput
                          //queue but may error as Count could now be zero.
}
lock(queue)
  if(queue.Count != 0)
    return queue.Dequeue; //thread-safe

ConcurrentQueue<int> cQueue = new ConcurrentQueue<int>();
/*...*/
int val;
if(cQueue.TryDequeue(out val))
  return val; //perfectly thread-safe and lock-free,
              //but more expensive than single-threaded use of Queue<int>
if(queue.Count!=0)
返回队列。退出队列//非线程安全,因为出列不是线程安全的。
如果(queue.Count!=0)
{
锁(队列)
return queue.Dequeue;//不是线程安全的,不会corrput
//队列,但可能会出错,因为计数现在可能为零。
}
锁(队列)
如果(queue.Count!=0)
返回队列。退出队列//线程安全
ConcurrentQueue cQueue=新ConcurrentQueue();
/*...*/
int-val;
if(cQueue.TryDequeue(out val))
返回val//完全线程安全且无锁,
//但是比队列的单线程使用更昂贵

我想我会更好地使用“extra int”。i、 e.在一个线程上,每次添加元素或从队列中删除元素时,我都会写入
int count=queue.count
,从另一个线程中我会写入
count
。顺便说一句,这是线程安全的吗?:)@javapowered:当然不安全,没有任何变化。您在
count
上仍然有一个竞赛条件。但是会出现什么问题呢?我会收到某种例外情况吗?意外值?我看不出会有什么不同。现在你的“count”int不是线程安全的,除非你锁定它。@Joe我不从我访问的不同线程访问
int
Queue
方法。我也可以声明
int
volatile
读取过时的值对我来说很好,但是我可以读取错误的值吗?i、 e.
int
的一半改变了,另一半没有改变。单词原子回答:不。但理论上,队列在排队或退队过程中可能会将其设置为某个奇怪的值,因此这仍然不是一个好主意。我只需要获得队列大小,就可以在UI中将其显示给用户,以供参考。我只是希望这不会在当前的实现中导致任何错误/异常,但是没有绝对的保证service pack或安全更新不会改变这一点。