日期:2014-05-20  浏览次数:20851 次

讨论一下多线程.200分其实也太少,不过这是我能给的最高分了.
这个贴开始在C++那边论坛发过,但没几个讨论的,不知道是不是我描述太烂了.
对于这个问题我一直是很有兴趣的(因为工作也是服务器上的应用,我较少做界面,用户交互应用),但是到现在我也没有找到很好的书来看.都是凭借自己的经验.
现在再在我们C#区发一下,我们这区够热度了.

讨论的命题:
程序把CPU拖到90%左右是否就是达到了完美效率

讨论这个前提肯定是排除垃圾消耗的代码,比如频繁启动新线程做无谓的运算。或无意义的消耗CPU时间。

只指有效代码。

比如操作一个int[] 有1000万个元素。读出来,然后做 1 个耗时1秒的操作(我们就把这个操作想成是数据库操作或者是socket send操作;每个元素耗时1秒)。如果不做多线程操作,显然我们就得消耗 1000万秒。这个时候运行这个单线程程
序CPU的消耗可能3%不到。但基本你的任务已经无法完成。
那么这样:我可以启动 10个线程,各自分配给他们各自要操作的索引段 如:0-100万,100万-200万。。。 等等这样int[]虽然是全局变量,但不用锁他。 然后10个线程各自工作。 这还是需要100万秒。


int[] 1000万数据 这个东西本身读取肯定是不需要消耗太多CPU的。 消耗时间的是后面的 操作。 而这个操作可能又有干耗以及实耗(抱歉,我就按这样形容了,干耗是指阻塞,不干活等待数据响应等等,而实耗指的是确切需要消耗CPU的动作。我后面也会以这样的认知去描述下面的问题)如果是实耗的话,我们没有办法避免。如果是单核心CPU你起10个线程和起1个线程都需要消耗X时间。而10个线程可能需要消耗更多时间,可能是X+Y 不过Y值很微小罢了。所以,我们多线程就是为了化干耗为0。所以理论上如果你达到化干耗为0,并且你这个程序持续工作X秒的话。 那么这X秒内CPU的占用率应该就会达到90%以上.


如果按我以上描述的去理解.那么下面这2个观点就是错误的.

比如:线程并非越多越好. -- 这个显然错误(或者说他是不分青红皂白的,不讲前提条件的).因为只要CPU还存在干耗的话,那么再创建1个线程肯定是更优化的选择(当然,也会有其他类似非阻塞而不加线程的更优选择)这个是非常显而易见的.比如现在你10个线程在操作 1000万数据. 每个线程要消耗1秒.而这1秒里有500毫秒是在阻塞.那么你启动10个线程显然是为了在你某些线程阻塞500毫秒的时候还有其他线程在继续工作.
但是!显然你并不能保证0干耗.这个时候如果10个线程的运算间隙都有 阻塞在干耗的话,能够显著提升效率的其中1个方案就是:再启动一个线程.

线程开启数量应该是CPU核心数+1 比如双核CPU就 可以开3个线程可以达到最高效率.这个显然是不完整的描述.(也就是错误的). 因为 如果你的程序干耗多的话,那么显然就和是否多核无关. 如果是实耗可能双核CPU开3个线程可以达到最高效率
关于线程数=CPU核心数+1 这个问题,我想大部分中级程序员都会对这个东西发窘,我开始也是不明所以,不知道这是讲的什么,只感觉这个东西在混淆视听.
而实际上,这个也很简单:也就是干耗为0的情况下(近似于0)如果你的CPU是多核的.那么请你不要再用单线程进行工作,而应该采取CPU核心数+1 的方案.

-------------------------------------

还谈谈c#的线程池与java的线程池.(这2个语言的线程池应该是近似用途与逻辑吧)
我对这个东西接触都不多,但从目测效率上感觉:这个东西的确没什么大的用处.在你需要高效运行的程序的时候最好是不要去用语言级别的线程池,因为总是感觉这个东西不是为了提高效率而设置的.具体是为什么场景设计的我也不知道(知道的可以说一说).反正提高效率尽量自己new线程,然后统一自己管理.

总结一下,多线程按本质来讲,我认为就是降低干耗,充分利用阻塞时间做其他事情.而从实际应用来讲可能有时候是:错开系统瓶颈,比如一个程序有数据库操作的话不要写成1串串下来的程序,而应该在写数据库操作的时候把线程分割开.

而多线程用到现在其实最麻烦也最难的是共享数据的线程安全.以及同步/效率的问题.

这贴用来讨论,欢迎拍砖,免得我一直脑袋里装错误看法

最后,第1次发200分的贴,不知不觉可以发200分的贴了,庆祝一下.

------解决方案--------------------
同喜 同喜 ,多线程是编程最高境界
------解决方案--------------------
多线程。。多核
------解决方案--------------------
仔细看了下,我感觉楼主理解得挺深的,真是受教了,有关这方面的知识,我一直是半知半解的,现在总算有个眉目了
------解决方案--------------------
学习来的...
------解决方案--------------------
多线程,一直不怎么会用,用一次就出一次问题啊。
------解决方案--------------------
你对线程的理解存在一些问题:

对于单CPU的机器来说,多线程对于大量数据的运算毫无益处,反而在线程调度上浪费时间,比如你这一段:

比如操作一个int[] 有1000万个元素。读出来,然后做 1 个耗时1秒的操作(我们就把这个操作想成是数据库操作或者是socket send操作;每个元素耗时1秒)。如果不做多线程操作,显然我们就得消耗 1000万秒。这个时候运行这个单线程程
序CPU的消耗可能3%不到。但基本你的任务已经无法完成。
那么这样:我可以启动 10个线程,各自分配给他们各自要操作的索引段 如:0-100万,100万-200万。。。 等等这样int[]虽然是全局变量,但不用锁他。 然后10个线程各自工作。 这还是需要100万秒。

对于单CPU机器来说,这是不可能发生的,微观时间内,每个时刻只能一个线程在运行。
即使对于多CPU机器来说,使用多线程能提高效率,也远不会是你描述的这样:10个线程同时工作,你有几个CPU或几个核心?
------解决方案--------------------
单CPU机器,多线程运用在不同性质的若干工作上,比如一个读数据库,一个网络收发,一个界面更新,这是合理的,同一性质的工作,尤其是可能会阻塞的工作,多线程经常被滥用。
------解决方案--------------------
说实话我多线程 懂的不多,仅仅是对上传限制,一般我在工作期间每个进程分割5线程 进行流量限制。
先占位,晚上来发表意见。
------解决方案--------------------
初级程序员路过,不懂!
------解决方案--------------------
学习的,有分得不?
------解决方案--------------------
线程并非越多越好,这是正确的,不管你是否运用多线程,大多数情况下,CPU仍然是空闲的时间居多,因为程序需要处理其他事情而非进行数据运算。

线程数=CPU核心数+1,这个倒是未必,看线程如何运用了。
------解决方案--------------------