python多线程

python多线程,第1张


title: python多线程
date: 2022-04-17 15:42:21
tags: python python多线程threading 多线程的概念

进程的相信大家都听说过,而线程可以理解为比进程更小一级的概念,一个进程内至少有一个线程,如果有多个线程,那么他们就共享进程的资源,共同完成进程的任务。

使用多线程一般有两个不同的目的:
一是把程序细分成几个功能相对独立的模块,防止其中一个功能模块阻塞导致整个程序假死(GUI程序是典型)
另一个就是提高运行效率,比如多个核同时跑,或者单核里面,某个线程进行IO *** 作时,另一个线程可以同时执行。

相比进程,线程有以下优点

  • 创建和销毁的代价比进程要小得多,尤其是在windows下,参考链接,而且线程间彼此切换所需的时间也远远小于进程间切换所需要的时间

  • 线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行。而由于同一进程下的线程之间共享数据空间,降低了通信的开销。

Python中的多线程threading

创建多线程有两种方法:第一种是继承treading.Tread,创建自己的线程子类;第二种是将需线程执行的函数传入线程的构造函数中,类似于multiprocessing的用法。

treading.Tread
# encoding:utf-8
import threading
import time
import random
class sleepThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print(self.name+ ' is created!')

    def run(self):
        randomTime = random.randint(1,9) # 生成 1~9的随机整数
        time.sleep(randomTime)
        print(self.name+ ' slept for '+str(randomTime)+' seconds' )

if __name__ == '__main__':
    threads = []
    for i in range(5):  # 创建5个进程
        th = sleepThread()
        threads.append(th)
        th.start()

    for t in threads:
        t.join() 
    print('all threads finished')

在上面的例子中,我们编写了自己的线程类sleepThread,然后创建了5个线程,用start()启动了各个线程,start()实际上是执行了线程类的run()函数。

将需要线程执行的函数传入线程构造函数中(推荐)

功能:一个线程不断往全局变量中写入数据,另一个线程不断从全局变量中读数据,不涉及到多个线程同时修改同一个变量时会发生冲突,所以没用到线程锁threadLock

import threading
import time

def sleepThread1(threadName, alist):
	for i in range(10):
		alist.append(i)
		time.sleep(1)

def sleepThread2(threadName, alist):
	while True:
		print(alist)
		time.sleep(2)

if __name__ == '__main__':

	gloabList = [] #全局变量,用来线程通信

	th1 = threading.Thread(target=sleepThread1, args=('Thread1',gloabList))
	th2 = threading.Thread(target=sleepThread2, args=('Thread2', gloabList),)

	th1.start() #开启线程th1
	th2.start() #开启线程th2
	th1.join()  #等待线程th1结束
	th2.join()  #等待线程th2结束

结果如下:

[0]
[0, 1, 2]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
多线程是否提高了效率

常常会有人说,因为python多线程只能使用一个核,所以多线程并没有提高效率。这句话一半对一半错。
python多线程只能使用一个核这句话针对部分python解析器如CPython等是正确的。原因是python的解析器(如CPython)因为内存管理问题设计了一个GIL(全局解析锁)。GIL保证了任何时候只有一个线程执行其字节码。这就限制了同一个进程内,只有一个线程在执行字节码,也就是说无论有多个线程,都只能用一个核。

第二句话说多线程并没有提高效率?这句话可以说对也可以说错。实际上针对CPU密集型的python进程,多线程没有提高效率;而针对IO密集型的进程,多线程提高了效率。

从上面的解释我们知道,GIL是限制了多线程并发执行的一个关键因素,而GIL仅仅是限制了同一时间同一进程只能有一个线程执行字节码,执行字节码是在CPU中的,对于CPU密集型的多线程,会一直占据着CPU导致其效果跟单线程一样。

而对于IO密集型的多线程,线程的执行时间会较多地消耗在IO上,因而CPU可供多线程轮流使用。比如说我曾用python爬取几个输入法的词库的,多线程比单线程要快了好几倍,原因就是爬虫属于IO密集型的任务,线程执行字节码所需的时间很短,而把大部分时间放在了下载和存储在本地上,线程执行完字节码后会释放GIL,从而其他线程也能够执行其字节码。从而在总体上提高了下载效率。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/715600.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存