【问题标题】:Cooperative/Non-preemptive threading avoiding deadlocks?协作/非抢占式线程避免死锁?
【发布时间】:2010-03-26 06:45:28
【问题描述】:

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

一些背景:

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

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

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

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

【问题讨论】:

  • 有趣的问题。标记此 C#,因为您的答案似乎表明这是您使用的语言。

标签: c# multithreading deadlock contextswitchdeadlock


【解决方案1】:

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

【讨论】:

  • 好的,要点。更多信息:我们已经这样做了。我们通过任务处理的所谓“让步”只是简单地返回,以便堆栈展开回调度程序。这意味着这个问题讨论中的所有 Yields 和 Sleeps 都是阻塞的。像这样:while(!xevent) Yield();我们已经处理了 DAG,这解决了所有其他情况。但是上面问题中的那个,如果你更仔细地研究它,就不是这样解决的。 B 和 C 之间的依赖性为零。只是它们必须同步。所以他们必须每个人都暂停并等待下一个运行的通知。
  • 这里的根本问题是每个任务在等待时都会占用堆栈。一种混乱的解决方案是将 B 和 C 分成 2 个任务。所以B变成B1和B2。这样 B1 和 B2 可以通过相互切换状态来运行。如果需要一个位于 B1 末尾的块,那么它可以在禁用 B2 后退出任务,因此 B2 在被 A 重新激活之前不会开始运行。这样,堆栈在两种情况下都会被释放。把可爱的代码分成这样的部分是很丑的。但如果没有更好的想法。
  • 也许我只是睡眠不足,但我仍然没有完全关注这里的问题。哪个线程有while (!xevent) Yield();,你希望哪个线程设置xevent?稍微改变一下规则,有一种完全不同的可能性:使用协作多任务处理来减少开销,但是使用一个看门狗定时器,它在死锁的情况下抢占。
  • 这是一个聪明的主意。唯一的问题是,如果它在死锁期间确实抢占了,那么需要运行的任务内部仍然有另一个线程阻塞。要继续它,抢占线程需要重新进入该任务,这将使该任务需要线程安全代码。该系统的优点在于所有任务都可以编写为非线程安全的(简单!),因为它们保证永远不会被另一个线程重新输入。当然,他们可能会在任何一次执行中获得不同的线程,但一次只能获得一个。
  • 我们想出了一个尝试的想法。我们正在考虑使用属性“IsDeadlockable”手动标记这些“危险”任务。然后,如果一个线程在一个任务中处于屈服或睡眠状态,则不允许它进入另一个标记为“IsDeadlockable”的任务。我认为这将解决这种特定情况。不幸的是,它不是自动发现的。我们看不到任何自动预见和防止这样的死锁的方法。那是因为调度器只有在死锁之后才知道自己会死锁,然后不可能在不破坏程序逻辑的情况下展开堆栈。
【解决方案2】:

好吧,我意识到理想的解决方案是如果 C# 语言支持真正的“延续”来展开堆栈并在稍后停止的地方继续。

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

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

真诚地, 韦恩

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 2011-11-23
    • 2017-12-17
    相关资源
    最近更新 更多