代码之家  ›  专栏  ›  技术社区  ›  Kibbee

为什么会这样线程。睡眠(0)解决我的问题,如何避免?

  •  9
  • Kibbee  · 技术社区  · 15 年前

    我正在开发一个客户机-服务器应用程序。在某些时候,在某些机器上,当有5个以上的客户机请求数据时,似乎会出现死锁。如果我介入调试问题,那么程序似乎正在处理。只需在我知道程序正在执行的地方设置一个断点,并使它命中断点几次,它就会完成。如果我插入线程。睡眠(0)在代码中的某些点上,主要围绕一些cpu密集型循环,它似乎几乎完全解决了问题。我现在的一个问题是如果我打电话线程。睡眠(0)太多,会减慢代码速度。如果调用不够,代码似乎处于死锁状态。尽管我可以验证它是否处于死锁状态,因为如果我进入代码,它会导致问题消失,这仅仅是因为我暂停了一个线程。

    有没有一个好的方法来追踪到底是什么导致了这一点。它似乎只发生在我的笔记本电脑是运行Vista,而不是在我的台式机是运行WindowsXP。然而,调试是不可能的,因为只要进入代码就可以解决问题。我看过一些评论线程。睡眠(0)是一种不好的做法,应该是不必要的,我不喜欢将巫术类型的代码放入我的应用程序中,我不明白为什么它必须存在。任何指点都将不胜感激。

    我还可以验证代码在“死锁”时是否仍在运行,因为如果我让它保持足够长的时间,它就会完成,只是所花的时间要高出许多数量级。我的意思是,当它处于这种“死锁”模式时,它实际上至少慢了100倍。CPU被固定在80-95%,所以它是工作的,尽管它所做的是我无法理解的,因为它要花很长时间才能完成任务。

    [详细信息] 因为这里的每个人都坚持认为这是一个死锁,所以我删除了所有执行任何锁定的代码。只有几行代码可以实现任何锁定。线程在大多数情况下是完全独立工作的,因此完全解除锁定的工作量不大。但问题依然存在。我的代码中没有更多的同步锁,没有更多的mutex,也没有我看到的导致死锁的东西,但是问题仍然存在。而且没有陷入僵局。它运行得很慢,尽管它消耗了所有的处理器资源。

    10 回复  |  直到 15 年前
        1
  •  11
  •   user7116    15 年前

    线程。睡眠(0)是收益率。我猜这会重新安排你的通话方式,以避免一些问题。我认为,如果你发布的代码产量,并运行在1000台机器上,你会得到很多错误报告。我猜您需要某种类型的锁/关键部分来避免死锁,因为有些地方的代码不是线程安全的。可能在你打电话给的图书馆里。

    1. 添加日志,看看问题是否仍然发生。 希望您能找出什么函数导致死锁
    2. 添加一些关键部分。 使用分而治之的方法,你应该能够缩小问题发生的范围。
        2
  •  4
  •   casperOne    15 年前

    如果不查看整个代码库,这是不可能回答的。

    好可怕 练习,你不应该这样做。您基本上是在改变导致死锁的代码计时,而不是从实际解决死锁条件开始。

        3
  •  3
  •   okutane    15 年前

    while (_field); // waiting for _field change in another thread
    

    ManualResetEvent

        4
  •  2
  •   mbeckish    15 年前

    当它陷入困境时,有多少个线程同时运行?

        5
  •  1
  •   Suroot    15 年前

    每次锁定互斥锁时打印一行,解锁时打印另一行。请记住在打印时包含函数名和线程id。应该能告诉你什么时候锁上了。似乎调用sleep(0)的竞争条件仍然会导致CPU使用循环来处理对函数的调用。因此导致一种固有的睡眠。

        6
  •  1
  •   Karl    15 年前

    我想你该离开电脑,走到白板上去了。分析每个元素是如何锁定的,以及在什么情况下它会小心地释放锁。五个线程可能是一个困难的问题,所以可以看看是否只有两个线程可以导致相同的情况。有些东西锁不好,你需要找到地方。

    除非你的代码不值得付出这么多努力,否则就离开线程。睡眠()在那里,因为它并没有真正伤害到你的表现非常宏伟的计划的事情。

        7
  •  1
  •   Dunk    15 年前

    你肯定有线程问题需要解决。打电话线程。睡眠(0)导致调度程序启动。这可能会给每个线程一个运行足够多的机会,以使事情正常工作。我不会把睡眠放在那里,就这样,因为这是一种工作了一段时间,然后一个完全不相关的变化最终打破了东西。

        8
  •  1
  •   dicroce    15 年前

    除非硬件强迫您这样做,否则您永远不应该使用sleep()。

    试着用不同的方式思考这个问题。考虑哪些数据需要在线程之间共享,并考虑如何将数据发送(即复制)给相关方,而不是共享访问。。如果你做得对,你实际上可能不需要任何互斥。。。

    记住,局部变量存在于不同的堆栈中,但是函数中的静态本质上是全局变量(当然,您需要仔细查看全局变量)。

        9
  •  0
  •   FryGuy    15 年前

    也许试着用一个工具,比如 Typemock Racer ?

    免责声明:我以前从未使用过这个工具。

        10
  •  0
  •   Joshua    15 年前

    是的,您可能遇到了计划程序过载。

    我真心希望不会。