Python线程和套接字

5
我有一个“我只是想理解它”的问题。首先,我在Ubuntu上使用Python 2.6.5。
在Python中,线程(通过thread模块)只是“线程”,它只是告诉GIL在一定时间内运行每个“线程”的代码块等等,实际上没有真正的线程。
因此,问题是 - 如果我在一个线程中有一个阻塞套接字,并且现在我发送数据并阻塞该线程约5秒钟。我期望会阻塞整个程序,因为它是一个C命令(sock.send)导致该线程阻塞。但是我惊讶地发现主线程继续运行。
那么问题是 - GIL如何能够在达到像send这样的阻塞命令后继续运行其余代码?难道这里不需要使用真正的线程吗?
谢谢。
3个回答

12

Python使用“真正的”线程,即底层平台的线程。在Linux上,它将使用pthread库(如果您感兴趣,这里是实现)。

Python线程的特别之处在于GIL:只有持有此全局锁的线程才能修改Python数据结构。因此,许多Python操作无法利用多个处理器核心。具有阻塞套接字的线程不会持有GIL,因此不会影响其他线程。

GIL经常被误解,使人们认为线程在Python中几乎没有用处。 GIL唯一防止的是在多个处理器核心上同时执行“纯”Python代码。如果您使用线程使GUI响应或在阻塞I / O期间运行其他代码,则GIL不会影响您。如果您使用线程在某些C扩展(如NumPy / SciPy)上并发地在多个处理器核心上运行代码,则GIL也不会影响您。


6

Python GIL维基页面中提到:

请注意,潜在的阻塞或长时间运行的操作(例如I/O、图像处理和NumPy数值计算)发生在GIL之外。


如果我有x个套接字(或其他I/O对象),并且它们都在后台(服务器)中处理,这是否意味着我有2个真实的线程:GIL和GIL之外的线程,所以如果一个套接字被阻塞,另一个套接字也会被阻塞?还是说我将有x个真实线程?(当我说“有x个线程”时,我的意思是-在同一时间可能有x个真实线程。即使只有不到一秒钟) - RoeeK
好的,在测试之后 - 我猜答案是x个真正的线程。现在这使得事情更加清晰了。 - RoeeK

5

GIL(全局解释器锁)只是一个锁,它本身不运行任何内容。相反,Python解释器会根据需要捕获和释放该锁。通常情况下,在运行Python代码时会保持锁定状态,但在调用较低级别的函数(例如sock.send)时会释放锁定。由于Python线程是真正的操作系统级线程,因此线程不能并行运行Python代码,但如果一个线程调用一个长时间运行的C函数,则GIL会被释放,直到第一个线程完成之前,另一个Python代码线程可以运行。


这可能是我迄今为止看到的关于该主题最简洁的摘要。一个小问题:解释器在遇到C代码时不会自动释放GIL,但长时间运行的C函数是否释放GIL取决于其自身的判断。 - FirefoxMetzger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接