Python多线程示例:理解线程并发与GIL影响

PDF格式 | 68KB | 更新于2024-08-29 | 165 浏览量 | 0 下载量 举报
收藏
在Python中,线程是一种并发执行的重要机制,它允许代码在单个进程中同时执行多个任务,从而提高程序的执行效率。然而,Python中的线程实现并非如所有编程语言那样直接支持并行计算,因为存在全局解释器锁(GIL)的概念,这限制了同一时刻只能有一个线程在执行Python字节码。尽管如此,GIL主要影响的是CPU密集型任务,对于IO密集型任务,如网络请求,GIL的影响较小,因为大部分时间都在等待I/O操作完成。 示例1:单线程网络请求 在这个例子中,我们创建了一个简单的函数`get_responses`,用于依次访问五个不同的URL。由于网络请求是阻塞的,即每个请求会等待服务器响应,因此线程的执行顺序就是url的列表顺序。当调用`get_responses`时,输出显示了每个URL的响应码和总耗时,可以看到线程按预定顺序执行,CPU在等待网络请求期间空闲。 ```python import time import urllib2 def get_responses(urls): start = time.time() for url in urls: print(url) resp = urllib2.urlopen(url) print(resp.getcode()) print("Elapsed time: %s" % (time.time() - start)) urls = ['http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com'] get_responses(urls) ``` 示例2:多线程网络请求 为了演示多线程的优势,我们创建了一个`GetUrlThread`类,继承自`threading.Thread`。这个类负责处理单个URL的请求。在`get_responses`函数中,我们创建了五个这样的线程,每个线程负责一个URL。这样,即使在等待网络响应时,其他线程也可以继续执行其他任务,提高了程序的并发性。 ```python import threading from urllib2 import urlopen class GetUrlThread(threading.Thread): def __init__(self, url): self.url = url super(GetUrlThread, self).__init__() def run(self): resp = urlopen(self.url) print(self.url, resp.getcode()) def get_responses(urls): threads = [] for url in urls: thread = GetUrlThread(url) thread.start() threads.append(thread) for thread in threads: thread.join() # 使用多线程执行 urls = ['http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com'] get_responses(urls) ``` 总结: 通过这两个示例,我们可以学习到在Python中如何使用线程进行网络请求,以及单线程和多线程的区别。单线程情况下,由于GIL的存在,尽管网络请求是异步的,但整体上仍然是串行的。而在多线程中,尽管仍然受到GIL的限制,但通过创建多个独立的线程,我们可以在等待网络响应的同时执行其他任务,从而提高代码的并发性能。然而,需要注意的是,如果任务过于简单或CPU密集型,多线程的优势可能并不明显,因为GIL会让CPU切换线程的成本变得较高。

相关推荐