繁体   English   中英

Interlocked.Exchange的安全性如何?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM