在CPython环境中,一个线程不从另一个线程获取GIL,除非它被阻止(比如使用sleep()
)或IO
在下面的服务器代码中,
# server.py
import socket
import sys
from threading import Thread
def echoHandler(conn, addr):
try:
while True:
data = conn.recv(16) # Blocking call
if data:
print(data.decode('utf-8'))
conn.sendall(data)
else:
break
finally:
print('Closing the connection from server')
conn.close()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 10006)
sock.bind(server_address)
sock.listen(1)
while True:
conn, addr = sock.accept()
t = Thread(target=echoHandler, args=(conn, addr))
t.daemon = True
t. start()
print('Waiting for another conn')
#client.py
import socket
import pdb
# pdb.set_trace()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 10006)
print('connecting to', server_address)
sock.connect(server_address)
while True:
try:
message = input().encode('utf-8')
except EOFError: #EAFP
print('Breaking ')
break
sock.sendall(message)
data = sock.recv(16) # Blocking call
print(data.decode('utf-8'))
print('close the socket')
sock.close()
问题:
一个线程何时有机会从另一个线程获取GIL以服务客户端?是conn.recv(16)
,允许服务器表现多线程吗?
答案 0 :(得分:4)
是的,在conn.recv(16)
期间(毕竟是网络I / O)不会保留GIL。
它还定期发布(2010年之前,每100个操作码;最近,可配置的5ms间隔)以避免线程饥饿。