线程在同步上花费的时间是否太高

本文关键字:时间 是否 同步 线程 | 更新日期: 2023-09-27 18:16:21

今天我使用Visual Studio 2010性能分析器分析了我的一个c#应用程序。具体来说,我正在分析"并发性",因为它似乎我的应用程序应该有比它所展示的更多的容量。分析报告显示,线程大约有70-80%的时间处于同步状态。

老实说,我不确定这是什么意思。这是否意味着应用程序处于活锁状态?

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

我意识到这是一个相当模糊的问题……我想我正在寻找一些关于线程同步状态的含义的解释。多少才算太多,为什么?75%真的很糟糕吗?我的线是不是太多了?还是我应该开始在其他领域找工作?

线程在同步上花费的时间是否太高

我不确定这是什么意思。

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

这是否意味着应用程序处于活锁状态?

也许!

为不熟悉术语的读者澄清一下:"死锁"是两个线程都在等待对方完成,因此它们永远等待。"活锁"是这样一种情况:两个线程试图避免死锁,但由于它们的错误选择,大部分时间都在等待。例如,想象一张有两个人的桌子,一把刀和一把叉。两个人都希望拿起两件器皿,用完,再放下。假设我拿起刀子,你拿起叉子。如果我们都决定等对方放下餐具,我们就陷入了僵局。如果我们都意识到我们即将陷入僵局,我放下刀,你放下叉子,然后我拿起叉子,你拿起刀,我们就会陷入僵局。我们可以无限地重复这个过程;我们都在努力解决这个问题,但我们的沟通不够有效,无法迅速解决问题。

然而,我的猜测是你不是在一个实时锁定的情况。我的猜测是,您只是在一次只能由一个线程访问的少数关键资源上存在巨大的争用。奥卡姆剃刀会指出,你应该采用简单的假设——许多线程轮流使用稀缺资源——而不是复杂的假设——一大堆线程都试图告诉对方"不,你先走"。

有~30多个长时间运行的线程绑定到单个AppDomain(如果有关系的话),并且一些线程非常繁忙(Ex. while(true) {_waitEvent.WaitOne(0);//做点什么})

听起来很糟糕。

我知道这是一个相当模糊的问题。

是的,它是。

多少是太多,为什么?

嗯,假设你想开车穿过城市,你和城市里的其他司机花75%的时间在红绿灯前等待其他司机。你告诉我:这是不是太多了,为什么?花一个小时堵在路上,却开了15分钟的车,这对有些人来说是完全可以接受的,但对另一些人来说是完全不能接受的。每次我在高峰时间乘坐SR 520,我都要花一个小时的时间在交通上,才能走完应该15分钟的距离;这对我来说是不可接受的,所以我现在坐公交车。

你和你的客户是否能接受这种糟糕的表现是你自己的决定。修复性能问题是非常昂贵的。你应该问的问题是,通过承担诊断和解决问题的费用,你将获得多少利润。

~75%真的很糟糕吗?

你的线程花费的时间是它们需要的四倍。我觉得不太好。

是不是线程太多了?

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

但在你的情况下,这是一个完全错误的技术问题。问"我是否有太多线程?"就像试图通过问"这个城市是否有太多汽车?"来解决交通拥堵一样。"正确的问题是"为什么这个城市里有这么多红绿灯,而这个城市本可以有高速公路的? ""问题不在于线程;

问题是他们在互相等待,而不是不停车地开车到达目的地。

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

我们究竟怎么知道?

在不真正了解程序结构的情况下,我只能真正告诉您同步在线程关系中意味着什么。我不能告诉你你的程序出了什么问题。

同步基本上意味着你协调也就是说,当必须对这些线程共享的资源采取行动时,线程的并发运行,以避免损坏你的数据

如果你有一个string,例如,你的两个线程正在写,然后,如果你没有线程同步(即使用AutoResetEvents或信号量等),那么一个线程可能在以某种方式改变字符串的中间,被操作系统中断(也许它的时间片是向上的),现在第二个线程可能开始从这个字符串中读取,这是一个不确定的状态。这将对你的程序造成破坏,所以为了避免这样的事情,以及许多其他可能由线程引起的错误,你同步对共享资源的访问,通过锁定,这样一次只有一个线程可以对它进行写/读操作,当另一个线程正在这样做时,任何其他线程都必须等待,直到我们的第一个线程释放了它持有的锁。

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

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

从本质上来说,这意味着你的程序并没有并发地工作,而是在串行中做一些事情,因为线程正在花费它们的时间等待其他线程。这意味着程序不能很好地实现真正的并发工作,顺便说一下,这并不一定是一件容易的事情,取决于情况,显然。

希望这对你有帮助。

线程同步有几种方式会降低性能:

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

关于多少是太多:同步是需要时间的,但并没有真正做任何有用的工作。因此,从性能的角度来看,理想的同步量总是为零。因此,无共享架构和不可变数据结构具有很高的价值。这两种技术都有助于以一种消除或减少同步需求的方式组织代码。

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