![](/img/trans.png)
[英]Thread safe generic alternative to Interlocked.Exchange and Interlocked.Exchange global struct support
[英]How safe are Interlocked.Exchange?
Beeing一个线程菜鸟,我正试图找到一种不用锁定对象的方法,允许我将线程池任务排入队列,使其具有最大并行度= 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);
}
}
也就是说,如果状态为Idle
,则以线程安全的方式将Run
方法排入队列。 它似乎在我的测试中工作正常,但由于这不是我的领域,我不确定。
是的,这将做你想要的。 当实际状态为Busy时,它永远不会允许您获得Idle的返回值,并且它将在同一操作中将状态设置为Busy,不会发生冲突。 到现在为止还挺好。
但是,如果您稍后使用ConcurrentQueue<T>
,为什么还要这样做呢? 为什么使用ThreadPool一次又一次地运行Run,而不是让一个线程使用TryDequeue连续从并发队列中获取数据?
事实上,有一个专门为此设计的生产者 - 消费者集合, BlockingCollection<T>
。 您的消费者线程只会调用Take
(如果需要,可以使用取消令牌 - 可能是个好主意),并且返回ConcurrentQueue<T>;
或者如果没有可用的值,则阻塞线程直到有可能采取的措施。 当一些其他线程将一个项目添加到集合时,它将通知尽可能多的消费者,因为它有数据(在您的情况下,不需要任何复杂的,因为您只有一个消费者)。
这意味着您只需要处理启动和停止单个线程,该线程将运行“无限”循环,这将调用col.Take
,而生产者调用col.Add
。
当然,这假设你有.NET 4.0+可用,但是你可能会这样做,因为你正在使用ConcurrentQueue<T>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.