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