2

有什么创意可以避免在不执行 O/S Thread.Sleep(10) 的情况下通过协作/非抢占式多任务处理在产量或睡眠上出现死锁?通常,yield 或 sleep 调用将回调调度程序以运行其他任务。但这有时会产生死锁。

一些背景:

这个应用程序对速度有巨大的需求,到目前为止,与同行业的其他系统相比,它的速度非常快。其中一种速度技术是协作/非抢占式线程,而不是从 O/S 线程进行上下文切换的成本。

高层设计了一个优先级管理器,它根据优先级和处理时间调用任务。每个任务执行一次“迭代”工作并返回以在优先级队列中再次等待。

非抢占式线程的棘手之处在于,当您希望特定任务在工作过程中停止并等待来自不同任务的其他事件后再继续时该怎么做。

在这种情况下,我们有 3 个任务,AB 和 C,其中 A 是一个控制器,必须同步 B 和 C 的活动。首先,A 启动 B 和 C。然后 B 产生,因此 C 被调用。当 C 让步时,A 看到它们都处于非活动状态,决定是 B 运行的时间,但还不是 C 的时间。Well B 现在卡在一个调用 C 的 yield 中,所以它永远无法运行。

4

2 回答 2

1

我认为处理这个问题的最干净的方法可能是将屈服(一个线程决定它已经处理了一段时间)与阻塞(等待特定事件)分开。这使得为​​已经产生的线程分配时间变得相对容易,但避免了尝试运行被阻塞的线程时出现死锁。通常,您希望对哪个线程阻塞在其他线程上进行拓扑排序,这样您就可以为其他线程等待的线程留出时间。这应该给出一个 DAG——图中的任何循环都表示死锁。

于 2010-03-26T07:19:58.290 回答
0

好吧,意识到这个问题的理想解决方案是,如果 C# 语言支持真正的“延续”来扩大堆栈并在稍后离开的地方继续。

如果没有,我们将通过允许在这种情况下的任务将“isInterrupted”标志设置为 true 并返回 - 从而展开堆栈来进行自己的临时替换。

然后,当调度程序想再次为该任务安排处理时间时,它会看到 isInterrupted 并跳过已经完成的处理,使用简单的 if 语句直接跳转到中断位置。

真诚的,韦恩

于 2010-03-29T22:00:04.497 回答