GIL如何与多线程服务器配合使用?

时间:2017-07-12 20:10:51

标签: python multithreading gil

在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),允许服务器表现多线程吗?

1 个答案:

答案 0 :(得分:4)

是的,在conn.recv(16)期间(毕竟是网络I / O)不会保留GIL。

它还定期发布(2010年之前,每100个操作码;最近,可配置的5ms间隔)以避免线程饥饿。