菜鸟教程 -- 学的不仅是技术,更是梦想!

Python 3 教程
Python3 教程 Python3 简介 Python3 环境搭建 Python3 VScode Python3 基础语法 Python3 基本数据类型 Python3 数据类型转换 Python3 解释器 Python3 注释 Python3 运算符 Python3 数字(Number) Python3 字符串 Python3 列表 Python3 元组 Python3 字典 Python3 集合 Python3 条件控制 Python3 循环语句 Python3 编程第一步 Python3 推导式 Python3 迭代器与生成器 Python3 with Python3 函数 Python3 lambda Python3 装饰器 Python3 数据结构 Python3 模块 Python __name__ Python3 输入和输出 Python3 File Python3 OS Python3 错误和异常 Python3 面向对象 Python3 命名空间/作用域 Python 虚拟环境的创建 Python 类型注解 Python3 标准库概览 Python3 实例 Python 测验

Python3 高级教程

Python3 正则表达式 Python3 CGI编程 Python3 MySQL(mysql-connector) Python3 MySQL(PyMySQL) Python3 网络编程 Python3 SMTP发送邮件 Python3 多线程 Python3 XML 解析 Python3 JSON Python3 日期和时间 Python3 内置函数 Python3 MongoDB Python3 urllib Python uWSGI 安装配置 Python3 pip Python3 operator Python math Python requests Python random Python OpenAI Python 有用的资源 Python AI 绘画 Python statistics Python hashlib Python 量化 Python pyecharts Python selenium 库 Python 爬虫 Python Scrapy 库 Python Markdown Python sys 模块 Python Pickle 模块 Python subprocess 模块 Python queue 模块 Python StringIO 模块 Python logging 模块 Python datetime 模块 Python re 模块 Python csv 模块 Python threading 模块 Python asyncio 模块 Python PyQt Python for 循环 Python while 循环
(追記) (追記ここまで)

Python threading 模块

Python 的 threading 模块是用于实现多线程编程的标准库之一。多线程允许程序在同一时间内执行多个任务,从而提高程序的效率和响应速度。

threading 模块提供了创建和管理线程的工具,使得开发者可以轻松地编写并发程序。

什么是线程?

你可以把线程想象成办公室里的员工:

  • 一个单线程程序就像只有一个员工,他必须顺序完成打印文档、回复邮件、泡咖啡等所有工作。

  • 多线程程序则像拥有多个员工,他们可以同时进行不同的任务,大大提高了工作效率。

在计算机科学中:

  • 进程:一个运行中的程序,拥有独立的内存空间(例如,你同时打开的浏览器和音乐播放器就是两个进程)。
  • 线程:进程内的一个独立执行流,是 CPU 调度的基本单位。同一个进程内的所有线程共享该进程的内存空间(如全局变量)。

为什么使用多线程?

在单线程程序中,任务是一个接一个地顺序执行的。如果某个任务需要等待(例如等待网络响应或文件读取),整个程序会被阻塞,直到该任务完成。而多线程可以让程序在等待某个任务的同时,继续执行其他任务,从而提高程序的整体性能。

Python 的线程与全局解释器锁 (GIL)

Python 有一个叫做 全局解释器锁 (Global Interpreter Lock, GIL) 的机制,GIL 确保了在任意时刻,只有一个线程可以执行 Python 字节码。

这意味着什么? 对于 CPU 密集型任务(如科学计算、图像处理),由于 GIL 的存在,多线程通常无法利用多核优势来提升计算速度,甚至可能因为线程切换的开销而变慢。

那么,Python 多线程的用武之地在哪里? 对于 I/O 密集型任务(如网络请求、读写文件、等待用户输入),线程在等待 I/O 操作完成时会释放 GIL,从而让其他线程运行。这可以显著提升程序的整体响应速度和效率,因为你在等待一个网页响应时,程序可以去处理另一个任务。


如何使用 threading 模块?

使用 threading 模块的第一步就是导入它:

import threading
import time # 用于模拟耗时操作

创建线程最基本的方式是使用 threading.Thread 类。

语法说明:

thread_obj = threading.Thread(target=函数名, args=(参数元组,))
  • target: 指定线程启动后要执行的函数。
  • args: 传递给 target 函数的参数,必须是元组类型。如果只有一个参数,需要写成 (参数,) 的形式。

1. 创建线程

在 Python 中,可以通过继承 threading.Thread 类或直接使用 threading.Thread 构造函数来创建线程。

方法 1:继承 threading.Thread

实例

import threading

class MyThread(threading.Thread):
def run(self):
print("线程开始执行")
# 在这里编写线程要执行的代码
print("线程执行结束")

# 创建线程实例
thread = MyThread()
# 启动线程
thread.start()
# 等待线程执行完毕
thread.join()
print("主线程结束")

方法 2:使用 threading.Thread 构造函数

实例

import threading

def my_function():
print("线程开始执行")
# 在这里编写线程要执行的代码
print("线程执行结束")

# 创建线程实例
thread = threading.Thread(target=my_function)
# 启动线程
thread.start()
# 等待线程执行完毕
thread.join()
print("主线程结束")

2. 线程同步

在多线程编程中,多个线程可能会同时访问共享资源,这可能导致数据不一致的问题。为了避免这种情况,可以使用线程同步机制,如锁(Lock)。

实例

import threading

# 创建一个锁对象
lock = threading.Lock()

def my_function():
with lock:
print("线程开始执行")
# 在这里编写线程要执行的代码
print("线程执行结束")

# 创建线程实例
thread1 = threading.Thread(target=my_function)
thread2 = threading.Thread(target=my_function)
# 启动线程
thread1.start()
thread2.start()
# 等待线程执行完毕
thread1.join()
thread2.join()
print("主线程结束")

3. 线程间通信

线程间通信可以通过队列(Queue)来实现。Queue 是线程安全的,可以在多个线程之间安全地传递数据。

实例

import threading
import queue

def worker(q):
while not q.empty():
item = q.get()
print(f"处理项目: {item}")
q.task_done()

# 创建一个队列并填充数据
q = queue.Queue()
for i in range(10):
q.put(i)

# 创建线程实例
thread1 = threading.Thread(target=worker, args=(q,))
thread2 = threading.Thread(target=worker, args=(q,))
# 启动线程
thread1.start()
thread2.start()
# 等待队列中的所有项目被处理完毕
q.join()
print("所有项目处理完毕")

常用类、方法及属性

1. 核心类

类/方法/属性说明示例
threading.Thread线程类,用于创建和管理线程t = Thread(target=func, args=(1,))
threading.Lock互斥锁(原始锁)lock = Lock()
threading.RLock可重入锁(同一线程可多次获取)rlock = RLock()
threading.Event事件对象,用于线程同步event = Event()
threading.Condition条件变量,用于复杂线程协调cond = Condition()
threading.Semaphore信号量,控制并发线程数sem = Semaphore(3)
threading.BoundedSemaphore有界信号量(防止计数超过初始值)b_sem = BoundedSemaphore(2)
threading.Timer定时器线程,延迟执行timer = Timer(5.0, func)
threading.local线程局部数据(各线程独立存储)local_data = threading.local()

2. Thread 对象常用方法/属性

方法/属性说明示例
start()启动线程t.start()
run()线程执行的方法(可重写)自定义类时覆盖此方法
join(timeout=None)阻塞当前线程,直到目标线程结束t.join()
is_alive()检查线程是否在运行if t.is_alive():
name线程名称(可修改)t.name = "Worker-1"
daemon守护线程标志(主线程退出时自动结束)t.daemon = True
ident线程标识符(未启动时为 None)print(t.ident)

3. Lock/RLock 常用方法

方法说明示例
acquire(blocking=True, timeout=-1)获取锁(阻塞或非阻塞)lock.acquire()
release()释放锁lock.release()
locked()检查锁是否被占用if not lock.locked():

4. Event 常用方法

方法说明示例
set()设置事件为真,唤醒所有等待线程event.set()
clear()重置事件为假event.clear()
wait(timeout=None)阻塞直到事件为真或超时event.wait(2.0)
is_set()检查事件状态if event.is_set():

5. Condition 常用方法

方法说明示例
wait(timeout=None)释放锁并阻塞,直到被通知或超时cond.wait()
notify(n=1)唤醒最多 n 个等待线程cond.notify(2)
notify_all()唤醒所有等待线程cond.notify_all()

6. 模块级函数/属性

函数/属性说明示例
threading.active_count()返回当前活跃线程数print(threading.active_count())
threading.current_thread()返回当前线程对象print(threading.current_thread().name)
threading.enumerate()返回所有活跃线程的列表for t in threading.enumerate():
threading.main_thread()返回主线程对象if threading.current_thread() is threading.main_thread():
threading.get_ident()返回当前线程的标识符(Python 3.3+)print(threading.get_ident())

实例

1. 基础线程创建

实例

import threading

def worker(num):
print(f"Worker {num} started")

threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()

for t in threads:
t.join()

2. 使用锁保护共享资源

实例

lock = threading.Lock()
count = 0

def increment():
global count
with lock: # 自动获取和释放锁
count += 1

threads = [threading.Thread(target=increment) for _ in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
print(count) # 输出: 10

3. 事件同步

实例

event = threading.Event()

def waiter():
print("Waiting for event...")
event.wait()
print("Event triggered!")

t = threading.Thread(target=waiter)
t.start()

# 主线程触发事件
threading.Event().wait(2.0) # 模拟延迟
event.set()
t.join()

4. 生产者-消费者模型(Condition)

实例

import random
from threading import Condition

queue = []
cond = Condition()
MAX_ITEMS = 5

def producer():
for _ in range(10):
with cond:
while len(queue) >= MAX_ITEMS:
cond.wait()
item = random.randint(1, 100)
queue.append(item)
print(f"Produced {item}")
cond.notify()

def consumer():
for _ in range(10):
with cond:
while not queue:
cond.wait()
item = queue.pop(0)
print(f"Consumed {item}")
cond.notify()

threading.Thread(target=producer).start()
threading.Thread(target=consumer).start()

注意事项

  1. 全局解释器锁(GIL):Python 的 GIL 会限制同一时间只有一个线程执行 Python 字节码。因此,在 CPU 密集型任务中,多线程可能不会带来性能提升。对于 I/O 密集型任务,多线程仍然是有益的。

  2. 线程安全:在多线程环境中,确保对共享资源的访问是线程安全的,避免数据竞争和死锁。

  3. 线程数量:创建过多的线程可能会导致系统资源耗尽,影响程序性能。合理控制线程数量,或使用线程池(ThreadPoolExecutor)来管理线程。


小测验

threading 模块知识小测验

1. Python 的全局解释器锁 (GIL) 主要影响以下哪种类型的多线程任务性能?
2. 创建线程对象后,应该调用哪个方法来启动线程的执行?
3. 当多个线程需要修改同一个全局变量时,为了避免数据错乱,最应该使用什么?
4. 主线程使用 thread.join() 的目的是什么?
AI 思考中...

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /