多线程和单线程的执行效率问题

一提到多线程一般大家的第一感觉就是可以提升程序性能,在实际的操作中往往遇到性能的问题,都尝试使用多线程来解决问题,但多线程程序并不是在任何情况下都能提升效率,在一些情况下恰恰相反,反而会降低程序的性能。这里给出两个简单的例子来说明下:

程序1:

 1 import threading
 2 from time import ctime
 3
 4 class MyThread(threading.Thread):
 5     def __init__(self, func, args, name):
 6         threading.Thread.__init__(self)
 7         self.name = name
 8         self.func = func
 9         self.args = args
10
11     def run(self):
12         print ‘starting‘, self.name, ‘at:‘,ctime()
13         apply(self.func, self.args)
14         print self.name, ‘finished at:‘, ctime()
15
16 def fun1(x):
17     y = 0
18     for i in range(x):
19         y+=1
20
21 def fun2(x):
22     y = 0
23     for i in range(x):
24         y+=1
25
26 def main():
27     print ‘staring single thread at:‘,ctime()
28     fun1(10000000)
29     fun2(10000000)
30     print ‘finished single thread at:‘,ctime()
31
32     t1 = MyThread(fun1,(10000000,),fun1.__name__)
33     t2 = MyThread(fun2,(10000000,),fun2.__name__)
34     t1.start()
35     t2.start()
36     t1.join()
37     t2.join()
38
39     print ‘all done‘
40
41 if __name__ == ‘__main__‘:
42     main()

该程序执行结果为:

staring single thread at: Sat Dec 08 10:27:11 2012
finished single thread at: Sat Dec 08 10:27:14 2012
starting  fun1  at:  Sat Dec 08 10:27:14 2012
starting  fun2  at:  Sat Dec 08 10:27:14 2012
fun1  finished at:Sat Dec 08 10:27:21 2012
fun2  finished at:Sat Dec 08 10:27:21 2012
all done

结果显示对于同样的问题多线程耗费了多一倍的时间,fun1,、fun2都是计算型程序,这就意味着两个代码都需要占用CPU资源,虽然采用了多线
程但CPU资源是唯一的(不考虑多CPU多核的情况),同一时刻只能一个线程使用,导致多线程无法真正的并发,相反由于线程的切换的开销,效率反而有明显
的下降。由此看以在单CPU的场景下对于计算密集型的程序,多线程并不能带来效率的提升。

程序2:

 1 import threading
 2 from time import ctime
 3
 4 class MyThread(threading.Thread):
 5     def __init__(self, func, args, name):
 6         threading.Thread.__init__(self)
 7         self.name = name
 8         self.func = func
 9         self.args = args
10
11     def run(self):
12         print ‘starting‘, self.name, ‘at:‘,ctime()
13         apply(self.func, self.args)
14         print self.name, ‘finished at:‘, ctime()
15
16 def fun1(x):
17     for i in range(x):
18         fd = open(‘1‘,‘w‘)
19         fd.close()
20
21 def fun2(x):
22     y = 0
23     for i in range(x):
24         y+=1
25
26 def main():
27     print ‘staring single thread at:‘,ctime()
28     fun1(15000)
29     fun2(50000000)
30     print ‘finished single thread at:‘,ctime()
31
32     t1 = MyThread(fun1,(15000,),fun1.__name__)
33     t2 = MyThread(fun2,(50000000,),fun2.__name__)
34     t1.start()
35     t2.start()
36     t1.join()
37     t2.join()
38
39     print ‘all done‘
40
41 if __name__ == ‘__main__‘:
42     main()

该程序执行结果为:

staring single thread at: Sat Dec 08 11:03:30 2012
finished single thread at: Sat Dec 08 11:03:46 2012
starting  fun1  at:  Sat Dec 08 11:03:46 2012
starting  fun2  at:  Sat Dec 08 11:03:46 2012
fun2 finished at: Sat Dec 08 11:03:55 2012
fun1 finished at: Sat Dec 08 11:03:58 2012
all done

结果显示这个程序采用多线程比单线程的效率有明显的提升。这是由于fun1主要是文件的操作,fun2是计算操作,单线程的情况下,虽然两个程序主
要使用不同的资源但是在线程内部只能串行执行,在IO操作的时候,CPU实际是无事可做。多线程的情况下,如果一个线程在等待IO操作,线程会马上调度到
另外一个线程上,并发的使用了不同的资源。

结论:

线程本身由于创建和切换的开销,采用多线程不会提高程序的执行速度,反而会降低速度,但是对于频繁IO操作的程序,多线程可以有效的并发。

对于包含不同任务的程序,可以考虑每个任务使用一个线程。这样的程序在设计上相对于单线程做所有事的程序来说,更为清晰明了,比如生产、消费者问题。

在实际的开发中对于性能优化的问题需要考虑到具体的场景来考虑是否使用多线程技术。

操作系统并发程序执行的特点:

并发环境下,由于程序的封闭性被打破,出现了新的特点:

①程序与计算不再一一对应,一个程序副本可以有多个计算

并发程序之间有相互制约关系,直接制约体现为一个程序需要另一个程序的计算结果,间接制约体现为多个程序竞争某一资源,如处理机、缓冲区等。

并发程序在执行中是走走停停,断续推进的。

与并行区别 编辑

并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它 只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

区别:并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。[2]

时间: 2024-10-19 08:44:24

多线程和单线程的执行效率问题的相关文章

并行的执行效率一定高于串行吗?(多线程的执行效率一定高于单线程吗?)

一.什么是串行?什么是并行? 串行:任务进行排队,一个一个执行: 并行:多个任务齐头并进.   二.单核.多核这两种情况下的并行. 单核情况下的并行:并非真的是多个任务同时进行的,是需要在这任务之间来回切换(即上下文切换)的. 多核情况下的并行:是几核,就能真正做到几核同时执行各自的任务. 三.任务的两大类型. “计算密集型”任务: 特点是要进行大量的计算,消耗CPU资源,比如计算圆周率.对视频进行高清解码等等,全靠CPU的运算能力. 这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在

WPF中多线程统计拆箱装箱和泛型的执行效率

WPF中多线程统计拆箱装箱和泛型的执行效率,使用的知识点有泛型.多线程.委托,从例子中可以看到使用泛型的效率至少提升2倍 MainWindow.xaml <Window x:Class="Box.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xa

多线程程序跑久了效率下降分析

最近在写一个搜索引擎,有个中间程序是分析分词结果文件,建立倒排索引.最初写的是单线程的,效率低到无语,于是又改成多线程的了.本以为万事大吉,可是在分析了将近2000文件的时候,效率低的和单线程的没什么区别了.打开任务管理器,线程数显示3(我设置的子线程数量最高为15,加上启动就有的,程序刚运行的时候线程数可以达到20个). 百度了下,Windows单个程序的线程数是有上限的,一般只能开到2000个左右.而我的程序中为了方便,把每个子线程都设置为detach状态了.这个状态下,线程结束时其他线程并

.Net中Task使用来提高代码执行效率

技术不断更新迭代,更高效的执行效率越来越被重视,所以对Task的使用进行了简单使用做了整理与大家分享. .Net 中有了Task后使多线程编程更简单使用和操作,下面粘上代码进行简单说明: /// <summary> /// 主线程执行 /// </summary> private static void GetVaule() { Console.WriteLine("我不是task,我的信息是,线程{0} 运行在线程id为{1}的线程上.是否是线程池中线程?:{2}&qu

你用什么方法检查PHP脚本的执行效率(通常是脚本执行时间)和数据库SQL的效率(通常是数据库Query时间),并定位和分析脚本执行和数据库查询的瓶颈所在?

腾讯 PHP脚本的执行效率 1, 代码脚本里计时. 2, xdebug统计函数执行次数和具体时间进行分析.,最好使用工具winCacheGrind分析 3, 在线系统用strace跟踪相关进程的具体系统调用. 数据库SQL的效率 sql的explain(mysql),启用slow query log记录慢查询. 通常还要看数据库设计是否合理,需求是否合理等.

关于提高python程序执行效率的思路和想法

相比编译型语言(C系列)python胜在简介的语法和优雅的动态编程体验,但是在执行效率上,python有解释性语言先天的劣势——执行效率较低,为了让编写出的程序获得更快的执行效率,开启此文章. python将编写好的程序源代码转为字节码,然后用PVM进行解释执行. 方法一:对代码进行优化 循环体中避免无用的赋值和计算,这在所用的编程中是通用的,而且效果显著. 第三方库的选择,比如对于html文本处理,正确使用 re 的解析速度显然会高于BeautifulSoup. 方法二:使用编译优化工具 Py

使用Android的硬件缩放技术优化执行效率

Unity3D研究院之使用Android的硬件缩放技术优化执行效率 http://www.xuanyusong.com/archives/3205 Android中GLSurfaceView在横竖屏切换时重新创建表面缓冲导致的问题 http://blog.k-res.net/archives/1702.html https://stackoverflow.com/questions/7185644/android-opengl-crazy-aspect-ratio-after-sleep

简单十招提高jQuery执行效率

1. 使用最新版本的jQuery jQuery的版本更新很快,你应该总是使用最新的版本.因为新版本会改进性能,还有很多新功能. 下面就来看看,不同版本的jQuery性能差异有多大.这里是三条最常见的jQuery选择语句: $('.elem') $('.elem', context) context.find('.elem') 我们用1.4.2.1.4.4.1.6.2三个版本的jQuery测试,看看浏览器在1秒内能够执行多少次.结果如下: 可以看到,1.6.2版本的运行次数,远远超过两个老版本.尤

参数探测(Parameter Sniffing)影响存储过程执行效率

如果SQL query中有参数,SQL Server 会创建一个参数嗅探进程以提高执行性能.该计划通常是最好的并被保存以重复利用.只是偶尔,不会选择最优的执行计划而影响执行效率. SQL Server尝试通过创建编译执行计划来优化你的存储过程的执行.通常是在第一次执行存储过程时候会生成并缓存查询执行计划.当SQL Server数据库引擎编译存储过程中侦测到有参数值传递进来的时候,会创建基于这些参数的执行计划.这种在编译存储过程中侦测参数值的方法,通常被称为"参数探测".有时参数探测会产