Python 多线程

Python 多线程简介

Python 是当今最受欢迎和多功能的编程语言之一,广泛应用于各个行业,包括 web 开发、机器学习和数据科学。鉴于其在相关领域(如机器学习和大数据)中的广泛应用和高需求,Python 已经超越 Java 成为顶级编程语言。

在本文中,我们将介绍 Python 多线程及其工作原理。我们将涵盖以下内容:

  1. 什么是多线程?
  2. 什么是进程
  3. 多线程的优势
  4. 守护线程(Daemon Thread)
  5. Python 多线程函数
    • threading.active_count()
    • threading.main_thread()
    • threading.Timer()
  6. 使用锁进行同步

什么是多线程?

多线程是指程序中可以独立于其他部分并发执行的一系列指令。

可以将它们视为进程中的不同单元,这些单元在被调度时可以独立完成任务。

当线程需要等待缓慢的外部操作(如网络请求或磁盘访问)完成时,它们会暂时休眠,从而使调度器可以将时间分配给其他线程执行。

什么是进程?

进程是计算机程序的一个可执行实例。

通常,一个进程是在单个控制流序列中执行的。

进程是操作系统分配资源的基本单位,每个进程包含一个或多个线程。

进程之间是隔离的,每个进程拥有自己的内存空间和系统资源。

多线程的优势

  1. 提高性能

    • 多核处理器:多线程程序在多核处理器系统上可以并行执行多个任务,从而显著提高性能。
    • I/O 绑定任务:多线程特别适用于 I/O 绑定任务,如网络请求和磁盘访问。当一个线程等待 I/O 操作完成时,其他线程可以继续执行,充分利用 CPU 时间。
  2. 资源共享

    • 共享内存:同一个进程中的线程可以共享内存,包括全局变量。如果一个线程修改了全局变量的值,这些更改对所有线程都可见,简化了数据共享和通信。

基本的 Python 多线程程序

以下代码是基本的 Python 多线程程序,我们导入了 threading 模块,并创建了一个名为 t 的线程。这个线程 t 将运行 show 函数。

python 复制代码
import threading

def show():
    print(f"Thread {threading.current_thread().name} is running")

# 创建一个线程
t = threading.Thread(target=show, name="MyThread")

# 启动线程
t.start()

# 等待线程完成
t.join()

print("Main thread has completed")

守护线程 (Daemon Thread)

守护线程是一种在后台运行的线程,它不会阻止主程序的退出。当主程序的所有非守护线程(即用户线程)结束时,守护线程也会自动终止。守护线程通常用于执行一些辅助性任务,如定期保存数据、监控系统状态等。

示例

下面是一个简单的 Python 示例,展示了如何创建和使用守护线程:

python 复制代码
import threading
import time

def background_task():
    count = 0
    while True:
        print(f"Background task {count}")
        count += 1
        time.sleep(1)

# 创建一个守护线程
t = threading.Thread(target=background_task, daemon=True)
t.name = "BackgroundThread"

# 启动线程
t.start()

# 主程序继续执行
print("Main thread is running...")

# 让主程序运行一段时间
time.sleep(5)

print("Main thread has completed")

关键点

  • 守护线程 :通过设置 daemon=True,线程成为守护线程。当主程序的所有非守护线程结束时,守护线程会自动终止。
  • 无限循环:守护线程通常用于执行无限循环的任务,这些任务不需要在主程序结束时显式地停止。
  • 线程名称 :可以通过 t.name 设置线程的名称,方便调试和日志记录。

Python 线程相关函数

Python 的 threading 模块提供了多种功能来管理和控制线程。以下是一些常用的线程相关函数及其示例:

1. threading.active_count()

这个函数返回当前正在执行的线程数量。

示例

python 复制代码
import threading

def show():
    print(f"Thread {threading.current_thread().name} is running")

# 创建并启动两个线程
t1 = threading.Thread(target=show, name="Thread1")
t2 = threading.Thread(target=show, name="Thread2")

t1.start()
t2.start()

# 输出当前活跃线程的数量
print(f"Number of active threads: {threading.active_count()}")

# 等待所有线程完成
t1.join()
t2.join()

输出

复制代码
Thread Thread1 is running
Thread Thread2 is running
Number of active threads: 3
Main thread has completed
2. threading.main_thread()

这个函数返回程序的主线程对象。

示例

python 复制代码
import threading

def show():
    print(f"Thread {threading.current_thread().name} is running")

# 创建并启动一个线程
t = threading.Thread(target=show, name="MyThread")
t.start()

# 获取主线程
main_thread = threading.main_thread()
print(f"Main thread name: {main_thread.name}")

# 等待线程完成
t.join()

输出

复制代码
Thread MyThread is running
Main thread name: MainThread
3. threading.Timer()

这个函数用于创建一个新的线程,并指定该线程在一定时间后启动。一旦启动,它会调用指定的函数。

示例

python 复制代码
import threading
import time

def delayed_task():
    print("Delayed task executed")

# 创建一个定时器线程,3秒后执行 delayed_task 函数
timer = threading.Timer(3, delayed_task)
timer.start()

# 主程序继续执行
print("Main thread is running...")

# 让主程序运行一段时间
time.sleep(5)

print("Main thread has completed")

输出

复制代码
Main thread is running...
Delayed task executed
Main thread has completed

代码解释

  1. threading.active_count()

    • 该函数返回当前正在执行的线程数量。
    • 在示例中,我们创建并启动了两个线程,然后输出当前活跃线程的数量。
  2. threading.main_thread()

    • 该函数返回程序的主线程对象。
    • 在示例中,我们获取了主线程的名称并输出。
  3. threading.Timer()

    • 该函数用于创建一个定时器线程,指定延迟时间和要执行的函数。
    • 在示例中,我们创建了一个定时器线程,3秒后执行 delayed_task 函数。

使用锁进行同步

在多线程编程中,锁(Lock)是一种重要的同步机制,用于确保多个线程不会同时访问共享资源,从而避免竞态条件(race conditions)。Python 的 threading 模块提供了 Lock 类来实现这一功能。Lock 类有两个主要方法:acquire()release()

方法说明
  1. acquire()

    • 用于获取锁。如果锁已经被其他线程持有,则调用 acquire() 的线程会被阻塞,直到锁被释放。
    • 可以选择性地传递一个超时参数 timeout,以防止线程无限期地等待锁。
  2. release()

    • 用于释放锁。如果锁未被当前线程持有,则会引发 RuntimeError 异常。
示例

下面是一个使用锁来同步两个线程的简单示例:

python 复制代码
import threading

# 共享资源
shared_resource = 0

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

def increment():
    global shared_resource
    for _ in range(1000000):
        lock.acquire()
        shared_resource += 1
        lock.release()

def decrement():
    global shared_resource
    for _ in range(1000000):
        lock.acquire()
        shared_resource -= 1
        lock.release()

# 创建两个线程
t1 = threading.Thread(target=increment)
t2 = threading.Thread(target=decrement)

# 启动线程
t1.start()
t2.start()

# 等待线程完成
t1.join()
t2.join()

# 输出最终的共享资源值
print(f"Final value of shared resource: {shared_resource}")

代码解释

  1. 导入 threading 模块

    python 复制代码
    import threading
  2. 定义共享资源

    python 复制代码
    shared_resource = 0
  3. 创建锁对象

    python 复制代码
    lock = threading.Lock()
  4. 定义 increment 函数

    python 复制代码
    def increment():
        global shared_resource
        for _ in range(1000000):
            lock.acquire()
            shared_resource += 1
            lock.release()
    • 这个函数会增加 shared_resource 的值 1000000 次。每次操作前先获取锁,操作完成后释放锁。
  5. 定义 decrement 函数

    python 复制代码
    def decrement():
        global shared_resource
        for _ in range(1000000):
            lock.acquire()
            shared_resource -= 1
            lock.release()
    • 这个函数会减少 shared_resource 的值 1000000 次。每次操作前先获取锁,操作完成后释放锁。
  6. 创建并启动线程

    python 复制代码
    t1 = threading.Thread(target=increment)
    t2 = threading.Thread(target=decrement)
    
    t1.start()
    t2.start()
  7. 等待线程完成

    python 复制代码
    t1.join()
    t2.join()
  8. 输出最终的共享资源值

    python 复制代码
    print(f"Final value of shared resource: {shared_resource}")

预期输出

由于 incrementdecrement 每个都执行 1000000 次,并且使用锁来同步,最终的 shared_resource 应该是 0。

注意事项

  • 死锁:如果一个线程获取了多个锁,但没有按正确的顺序释放,可能会导致死锁。使用锁时要小心,确保每个锁都能正确地被释放。
  • 性能:频繁地获取和释放锁可能会影响性能,因此在实际应用中需要权衡同步的需求和性能的影响。

总结

在这篇文章中,我们探讨了 Python 多线程的基本概念。我们学习了与多线程相关的不同函数和对象,包括:

  1. threading.active_count()

    • 用于获取当前正在执行的线程数量。
  2. threading.main_thread()

    • 用于获取程序的主线程对象。
  3. threading.Timer()

    • 用于创建一个定时器线程,指定延迟时间后执行特定的函数。
  4. 锁(Lock)

    • 用于同步多个线程,避免竞态条件。锁的主要方法有 acquire()release()

通过这些基本概念和示例,你可以更好地理解和使用 Python 的多线程功能来开发高效的并发应用程序。

相关推荐
学Java的bb3 分钟前
MybatisPlus
java·开发语言·数据库
讓丄帝愛伱4 分钟前
Mybatis Log Free插件使用
java·开发语言·mybatis
心之伊始7 分钟前
Netty线程模型与Tomcat线程模型对比分析
java·开发语言
MasonYyp11 分钟前
简单使用Marker
python·语言模型
专注VB编程开发20年42 分钟前
csdn手机app应该增加导入word格式markdown格式,或者输入网址自动导入
开发语言
std8602143 分钟前
使用 python-docx 和 difflib 对比 Word 文档
python
ChineHe1 小时前
Golang并发编程篇001_并发编程相关概念解释
开发语言·后端·golang
java1234_小锋1 小时前
TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 使用Keras实现分类问题
python·深度学习·tensorflow·tensorflow2
@大迁世界1 小时前
Promise.all 与 Promise.allSettled:一次取数的小差别,救了我的接口
开发语言·前端·javascript·ecmascript