在同步中花费的线程时间是否过高?

今天,我使用Visual Studio 2010性能分析器分析了我的一个C#应用程序。 具体来说,我正在对“ 并发 ”进行概要分析,因为看起来我的应用程序应该具有更多的容量然后才能进行演示。 分析报告显示,线程在同步状态下花费了大约70-80%的时间。

说实话,我不确定这意味着什么。 这是否意味着应用程序遭受了锁定状态?

对于上下文…有大约30个长时间运行的线程绑定到单个AppDomain( 如果这很重要 )并且一些线程非常繁忙(例如while(true) { _waitEvent.WaitOne(0); //do stuff } )。

我意识到这是一个相当模糊的问题……我想我正在寻找一些关于线程同步状态含义的阐释。 多少钱,为什么? ~75%真的很糟糕吗? 我有太multithreading吗? 或者我应该开始寻找其他领域?

我不确定这意味着什么。

这意味着线程平均花费75%的时间等待另一个线程完成一些工作。

这是否意味着应用程序遭受了锁定状态?

也许!

为不熟悉术语的读者澄清:“死锁”是指两个线程都在等待彼此完成,因此他们会永远等待。 “实时锁定”是两个线程试图避免死锁的情况,但由于选择不当,无论如何都要花大部分时间等待。 想象一下,例如一张有两个人的桌子,一把叉子和一把刀。 两个人都希望拿起两个器具,使用它们,然后把它们放下。 假设我拿起刀子你拿起叉子。 如果我们都决定等待对方放下器具,我们就陷入僵局。 如果我们都意识到我们即将陷入僵局,我放下了刀子,你放下叉子, 然后我拿起叉子,你拿起刀子 ,我们就锁定了。 我们可以无限期地重复这个过程; 我们都在努力解决这个问题,但我们没有足够的沟通来快速实际解决问题。

但是,我的猜测是你没有处于锁定状态。 我的猜测是,您只需要对少量关键资源进行大量争用,这些资源一次只能由一个线程访问。 Occam的Razor表明你应该假设一个简单的假设 – 许multithreading轮流使用稀缺资源 – 而不是复杂的假设 – 一大堆线程都试图告诉对方“不,你先走”。

有大约30个长时间运行的线程绑定到单个AppDomain(如果这很重要)并且一些线程非常繁忙(例如,(true){_ waitEvent.WaitOne(0); // do stuff})。

听起来很可怕。

我意识到这是一个相当模糊的问题。

是的。

多少钱,为什么?

好吧,假设你正试图穿越城镇,你和城里的其他所有司机花了75%的时间停在交通灯等待其他司机。 你告诉我:那太多了,为什么? 花一小时的交通来驾驶15分钟的距离可能是一些人完全可以接受的,而其他人完全不能接受。 每次我在高峰时间乘坐SR 520,我都需要花一个小时的时间来移动距离,这需要15分钟。 这是我不能接受的,所以现在我坐公共汽车。

您和您的客户是否接受这种糟糕的性能是您的电话。 修复性能问题很昂贵 。 您应该问的问题是,通过承担诊断和解决问题的费用,您将获得多少利润。

~75%真的很糟糕吗?

你的线程花费的时间比他们需要的时间长四倍。 对我来说似乎不太好。

我有太multithreading吗?

你几乎肯定会这样做,是的。 30很多。

但在您的情况下,这完全是错误的技术问题。 问“我有太multithreading吗?” 通过询问“ 这个城市有太多的汽车吗? ”试图解决交通拥堵问题。正确的问题是“ 为什么这个城市里有这么多交通信号灯可能有高速公路? ”问题不在于线程; 问题是他们正在等待而不是停下来直到他们的目的地。

我应该开始寻找其他领域吗?

我们怎么知道呢?

在没有真正了解程序结构的情况下,我只能真正告诉您同步对线程的意义。 我无法真正告诉你程序中的问题是什么。

同步基本上意味着您可以协调,以便在必须对这些线程共享的资源执行操作时说并发运行线程,以避免数据损坏

如果您有一个string ,例如,您的两个线程正在写入,那么,如果您没有线程同步(即使用AutoResetEvents或Semaphores等),那么一个线程可能正在改变一些线程中的字符串时尚,被操作系统打断(也许它的时间片已经上升),现在第二个线程可能从这个字符串开始读取,这个字符串处于不确定状态。 这会对您的程序产生影响,因此为了避免这些事情以及线程可能导致的许多其他可能的错误,您可以通过锁定同步对共享资源的访问,这样一次只能有一个线程可以写入/读取/来自它,以及任何其他想要这样做另一个正在这样做的线程 ,必须等到我们的第一个线程释放它所持有的锁。

在一个非常简单的解释中,这是什么线程同步意味着它是什么意思。
线程有更多的东西,但这是整本书的主题。

至于你的“线程同步状态”可能意味着什么,我猜这意味着很multithreading都花时间等待持有一些共享资源的其他线程。

从本质上讲,这意味着你的程序实际上并不是同时工作,而是串行工作 ,因为线程花时间等待其他线程 。 这意味着程序编写得不是很好,不能真正同时工作,顺便说一下, 根据具体情况 ,这显然不是一件容易的事。

希望这可以帮助。

线程同步有几种方法可以扼杀性能:

  1. 实现同步的指令需要时间来执行,特别是对于需要转换到内核模式的同步例程,例如Thread.Sleep()。 在最坏的情况下,频繁调用同步例程的单独线程引入了大量开销,没有真正的好处。
  2. 每当多个线程同时需要对资源进行独占访问时,至少有一个线程会等待。 这里最糟糕的情况是,每个人都需要经常访问一些中央资源。 在这种情况下,multithreading代码很有可能成为一次使用一个线程的昂贵,缓慢和复杂的方法。

至于多少太多:同步是需要时间但却没有做任何有用工作的事情。 因此,从性能角度来看,理想的同步量始终为零。 因此,无共享体系结构和不可变数据结构的高价值。 两者都是帮助组织代码以消除或减少同步需求的技术。

当然,世界并不理想,因此一定程度的同步通常是不可避免的。 但即使这样,也应该使用尽可能最轻的构造。 例如,当Interlocked中的方法执行时,请不要使用lock语句。 或者通过设计线程将工作产品批量发送到中央数据结构,而不是进行大量的高频更新,降低需要发生的频率。