0Pricing
Python Academy · 课时

线程与 GIL

理解 Python 线程的限制

线程与 GIL 是 CoddyKit 上的免费 Python Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。

什么是线程?

线程是一个进程内部独立的执行流。Python 的 threading 模块可以让您在一个程序中并发运行多个函数。

import threading

def worker():
    print('hello from thread')

t = threading.Thread(target=worker)
t.start()
t.join()
print('main done')

启动多个线程

您可以启动多个线程。每个线程都会运行其目标函数。join() 会让主线程等待某个线程完成。

import threading

def task(name):
    print('task', name)

threads = [threading.Thread(target=task, args=(i,)) for i in range(3)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print('all finished')

全局解释器锁

CPython 具有全局解释器锁(GIL):同一时刻只有一个线程执行 Python 字节码。这意味着对于纯 Python 的 CPU 工作,线程无法带来真正的并行加速。

import sys
print('Running on:', sys.implementation.name)
print('Only one thread runs Python bytecode at a time due to the GIL')

线程仍然有用的场景

线程非常适合I/O 密集型工作:网络请求、磁盘读取和等待。当一个线程等待时,GIL 会被释放,另一个线程便可以运行。

import threading, time

def fake_io(name):
    time.sleep(0.1)
    print('done', name)

start = time.perf_counter()
ts = [threading.Thread(target=fake_io, args=(i,)) for i in range(3)]
for t in ts: t.start()
for t in ts: t.join()
print('elapsed about 0.1s, not 0.3s')

CPU 密集型工作不会加速

对于繁重的计算,添加线程不会让程序更快,因为 GIL 会将它们串行化。对于 CPU 工作,请改用 multiprocessing。

import threading

def burn():
    total = 0
    for i in range(1000000):
        total += i
    return total

t = threading.Thread(target=burn)
t.start()
t.join()
print('CPU-bound: threads share one core under the GIL')

守护线程

主程序退出时,守护线程会自动终止。如果您不需要等待某个后台辅助线程完成,可以使用守护线程。

import threading, time

def background():
    time.sleep(0.05)
    print('background tick')

t = threading.Thread(target=background, daemon=True)
t.start()
t.join()
print('main exits')

命名和识别线程

每个线程都有名称和 ID。threading.current_thread() 会返回当前运行的线程对象,便于记录日志。

import threading

def show():
    t = threading.current_thread()
    print('running in', t.name)

t = threading.Thread(target=show, name='Worker-1')
t.start()
t.join()
print('main thread:', threading.current_thread().name)

继承 Thread

除了传入目标函数,您还可以继承 Thread 并重写 run()。当线程需要维护自己的状态时,这种方式很有用。

import threading

class Greeter(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.who = name
    def run(self):
        print('hi', self.who)

g = Greeter('Sam')
g.start()
g.join()

从线程返回结果

目标函数的返回值会被丢弃。要收集结果,请将它们写入共享结构中(稍后您会看到队列等更安全的工具)。

import threading

results = {}

def compute(key):
    results[key] = key * key

ts = [threading.Thread(target=compute, args=(i,)) for i in range(4)]
for t in ts: t.start()
for t in ts: t.join()
print(results)

统计活动线程

threading.active_count() 会告诉您当前存活的线程数,其中包括主线程。

import threading, time

def wait():
    time.sleep(0.05)

ts = [threading.Thread(target=wait) for _ in range(2)]
for t in ts: t.start()
print('active now:', threading.active_count())
for t in ts: t.join()
print('active after join:', threading.active_count())

选择线程还是进程

经验法则是:使用线程处理 I/O 密集型并发,使用进程实现 CPU 密集型并行。原因就在于 GIL。

tasks = {'download files': 'threads', 'crunch numbers': 'processes', 'call APIs': 'threads'}
for task, choice in tasks.items():
    print(task, '->', choice)

快速检查

检验您对线程和 GIL 的理解。

回顾

您学习了线程和 GIL:

  • 线程通过 threading.Thread 在一个进程内部并发运行。
  • GIL 会将 Python 字节码的执行串行化。
  • 线程适合 I/O 密集型工作;进程适合 CPU 密集型工作。
  • 请使用 start()、join()、守护线程和继承来管理线程。

接下来:使用 ThreadPoolExecutor 规范地管理线程。

常见问题解答

「线程与 GIL」课时是免费的吗?

是的 — 「线程与 GIL」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「线程与 GIL」这节课中我会学到什么?

理解 Python 线程的限制 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Python Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「线程与 GIL」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Python Academy 课中编写并运行代码吗?

能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 线程与 GIL
  2. ThreadPoolExecutor
  3. multiprocessing 基础
  4. 安全共享数据
← 返回 Python Academy