【发布时间】:2015-07-16 07:13:49
【问题描述】:
背景:
在调试应用程序时,我遇到了这个功能
boolean IsThreadGood(Thread t)
{
return t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin;
}
我认为这是一个错误,因为在 return 语句中发生的逻辑比较不是原子的,因此我认为线程 t 可以在执行表达式时改变状态。为了检查这个想法,我将代码更改为以下代码,以便可以放置断点:
bool IsThreadGood(Thread t)
{
if (t.IsAlive)
{
if (t.ThreadState == ThreadState.Running)
{
return true;
}
if (t.ThreadState == ThreadState.WaitSleepJoin)
{
return true;
}
}
return false;
}
我在内部 if 语句上放置了断点,很快就看到了我的怀疑。当代码到达第一个断点时 Thread t 的 ThreadState 为 WaitSleepJoin 并且当我将代码单步执行到下一个 if 语句时 Thread t 已切换状态并具有 Running 的 ThreadState ,因此两个测试均失败并从该方法返回 false应该返回 true。
我的问题:
我怎样才能以线程安全的方式从另一个线程检查一个线程的状态?
我的想法和我的研究:
如果我可以使语句原子化,它会起作用。我在 Google 上搜索了一些内容,例如“如何在 c# 中使语句成为原子”,并得到了很多涉及锁的结果——这不是我想要的,因为据我所知,锁不会使代码原子化。
如果我可以从执行该方法的线程中挂起 Thread t,那么我可以安全地检查它的状态。我在这里找到的是过时的功能 Suspend 和 Resume。 Microsoft 强烈建议不要使用这些。
以某种方式更改线程 t 以实现同步。不是一个选择。该代码是可重用的代码,已被不同的客户端以不同的方式重用,线程 t 是客户端代码。不可能更改所有客户端。
我不是多线程专家,所以如果我的任何假设不正确或我对多线程的理解不正确,请随时指出。
【问题讨论】:
-
如果线程在所有检查“goodness”的点上都是“good”,则当前函数返回 true。我不确定找到一个原子解决方案是否有意义,如果确实有的话,因为在函数返回 true 后线程可能立即变得不好。大概此代码适用于已知线程不会以任何频率从良好切换到不良的场景。
-
var state = t.ThreadState; return state == ThreadState.Running || state == ThreadState.WaitSleepJoin; -
@Eric J 该方法用于从队列中移除未运行的线程。如果该方法在队列中留下一个未运行的线程,那没关系,因为下次运行该方法时它将被删除。但是尝试删除仍在运行的线程会导致问题。
-
那么当前的代码应该没问题。它必须通过所有“好”检查才能仍然被认为是“好”。如果它没有通过任何一项检查,它就没有运行,并且不会自行返回到运行状态。
-
旁注:实现合理工作的线程池很难。您可能需要考虑依赖框架提供的工具 - 即带有 async/await 的任务可能是合适的。
标签: c# multithreading