作为一个线程程序,我试图找到一种方式w/o锁定对象,它允许我对线程池任务进行排队,使它具有最大程度的并行性= 1。
这段代码能像我想的那样做吗?
private int status;
private const int Idle = 0;
private const int Busy = 1;
private void Schedule()
{
// only schedule if we idle
// we become busy and get the old value to compare with
// in an atomic way (?)
if (Interlocked.Exchange(ref status, Busy) == Idle)
{
ThreadPool.QueueUserWorkItem(Run);
}
}也就是说,如果状态为Run,则以线程安全的方式对该方法进行排队。这似乎在我的测试中很好,但由于这不是我的领域,我不确定。
发布于 2014-01-08 12:46:46
是的,这能做你想做的事。当状态实际上很忙时,它将永远不允许您获得Idle的返回值,并且它将在同一操作中将状态设置为繁忙,而不会发生冲突。到目前一切尚好。
但是,如果以后使用的是ConcurrentQueue<T>,为什么还要这样做呢?为什么要使用ThreadPool来一次又一次地运行队列,而不是让单个线程使用TryDequeue不断地从并发队列中获取数据?
事实上,有一个生产者-消费者的集合,是专门为此设计的,BlockingCollection<T>。您的使用者线程只需调用Take (如果有必要,可以使用取消令牌--这可能是个好主意),如果返回ConcurrentQueue<T>;中的值,或者如果没有可用的值,则阻塞线程,直到有东西可取为止。当其他线程向集合中添加项时,它会通知尽可能多的使用者(在您的情况下,不需要任何复杂的东西,因为您只有一个使用者)。
这意味着您只需处理启动和停止单个线程,该线程将运行一个“无限”循环,该循环将调用col.Take,而生产者则调用col.Add。
当然,这假设您有.NET 4.0+可用,但同样,您可能会这样做,因为您正在使用ConcurrentQueue<T>。
https://stackoverflow.com/questions/20994833
复制相似问题