这是ConcurrentDictionary和ConcurrentQueue线程安全的组合吗?

我在以下代码中使用.NET 4中的ConcurrentDictionary和ConcurrentQueue类。

这段代码是线程安全的吗? 如果没有,我怎样才能使它成为线程安全的?

public class Page { public string Name {get; set; } } public class PageQueue { private ConcurrentDictionary<int, ConcurrentQueue> pages = new ConcurrentDictionary<int, ConcurrentQueue>(); public void Add(int id, Page page) { if (!this.pages.ContainsKey(id)) this.pages[id] = new ConcurrentQueue(); this.pages[id].Enqueue(page); } public Page GetAndRemove(int id) { Page lp = null; if(this.pages.ContainsKey(id)) this.pages[id].TryDequeue(out lp); return lp; } } 

演示:

  public class Demo { public void RunAll() { for (int i = 0; i  Run()); } public void Run() { PageQueue pq = new PageQueue(); pq.Add(1, new Page()); pq.GetAndRemove(1); } } 

正如@Femaref正确指出的那样,代码中存在一些缺陷。 我建议您利用ConcurrentDictionary 提供的许多方法,使您的代码在线程安全,而无需使用lock语句:

 public class PageQueue { private ConcurrentDictionary> pages = new ConcurrentDictionary>(); public void Enqueue(int id, Page page) { var queue = this.pages.GetOrAdd(id, _ => new ConcurrentQueue()); queue.Enqueue(page); } public bool TryDequeue(int id, out Page page) { ConcurrentQueue queue; if (this.pages.TryGetValue(id, out queue)) { return queue.TryDequeue(out page); } page = null; return false; } } 

您可以(也可能会)遇到这些语句的问题:

  if (!this.pages.ContainsKey(id)) this.pages[id] = new ConcurrentQueue(); 

  if(this.pages.ContainsKey(id)) this.pages[id].TryDequeue(out lp); 

因为可以在if语句和Assignment / Dequeue之间更改ConcurrentDictionary 。 对锁定对象使用锁定代码的那些部分,例如:

 public class PageQueue { private ConcurrentDictionary> pages = new ConcurrentDictionary>(); private object locker = new object(); public void Add(int id , Page page) { lock(locker) { if (!this.pages.ContainsKey(id)) this.pages[id] = new ConcurrentQueue(); } this.pages[id].Enqueue(page); } public Page GetAndRemove(int id) { Page lp = null; lock(locker) { if(this.pages.ContainsKey(id)) this.pages[id].TryDequeue(out lp); } return lp; } }