Python线程详解攻略
前言
多线程是一种常用的并发编程方式,在Python中也有相应的模块支持多线程。本攻略将从以下几个方面对Python线程进行详细的讲解。
- 线程的基本概念
- Python中的多线程模块(threading)
- 线程的生命周期
- 线程锁的概念
- 线程的同步与阻塞
线程的基本概念
线程是操作系统能够进行运算调度的最小单位。一个进程可以拥有多个线程,每个线程都运行在进程的地址空间中,并可通过共享数据实现通信。线程可以在单个CPU上执行多个任务,因此多线程常被用来提高程序的执行效率。
Python中的多线程模块(threading)
Python中的多线程模块为threading
,利用该模块可以便捷地创建和管理线程。以下是threading
模块中最常用的类的使用方法。
Thread类
Thread
类是Python中表示线程的类,使用Thread
类可以创建新的线程。以下是使用Thread
类创建线程的示例。
import threading
def worker(num):
print("Worker %d is running..." % num)
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
t.start()
上述代码中,target
参数表示线程运行的目标函数,args
参数表示目标函数的参数列表。创建完线程后,调用其start
方法即可启动线程。
Lock类
Lock
类是Python中用于线程同步的类,可以通过该类实现多个线程之间的同步。以下是使用Lock
类的示例。
import threading
num = 0
lock = threading.Lock()
def add_num():
global num
lock.acquire() # 获得锁
try:
num += 1
finally:
lock.release() # 释放锁
for i in range(10):
threading.Thread(target=add_num).start()
print("Num:", num)
上述代码中,由于s+=1
操作非原子操作,因此可能会出现竞争状态。为了避免竞争状态,使用Lock
类对其进行加锁。上述代码中,lock.acquire()
用于获得锁,lock.release()
用于释放锁。
线程的生命周期
线程的生命周期可以分为以下四个阶段:
- 新建状态
- 就绪状态
- 运行状态
- 终止状态
在线程创建后,线程处于新建状态,等待系统分配资源。当系统分配了相应的资源后,线程进入就绪状态。一旦进入就绪状态,线程就有机会被分配到CPU来执行,在CPU执行后进入运行状态。当程序执行结束或遇到异常时,线程进入终止状态。
线程锁的概念
线程锁是用于控制对共享资源的存取的工具。互斥锁是线程锁的一种,它保证同一时间只有一个线程能够访问共享资源。线程锁的使用可以避免出现竞争状态和死锁现象。
线程的同步与阻塞
当线程被阻塞时,它将无法继续执行,直到一定条件得以满足。线程同步是指多个线程按照一定的顺序进行执行,主要用于多线程之间共享同一个资源的场景。线程同步可以避免多线程之间出现竞态条件的情况。
示例说明
示例一:使用多线程实现计算器
import threading
num1 = input("请输入第一个数:")
num2 = input("请输入第二个数:")
def add(a, b):
print("a + b = ", a+b)
def subtract(a, b):
print("a - b = ", a-b)
t1 = threading.Thread(target=add, args=(num1, num2))
t2 = threading.Thread(target=subtract, args=(num1, num2))
t1.start()
t2.start()
t1.join()
t2.join()
print("主线程结束")
在上述代码中,我们定义了两个函数add
和subtract
实现了两数之和和两数之差的计算。我们使用Thread
类创建了两个线程,每个线程执行一个函数。在线程结束后,我们使用join
方法保证主线程等待两个子线程执行完成后再结束。
示例二:多线程下载文件
import threading
import requests
url_list = [
"http://www.sina.com.cn/",
"http://www.baidu.com/",
"https://cn.bing.com/",
"http://www.qq.com/",
"http://www.taobao.com/",
]
def download(url):
res = requests.get(url)
print("%s下载完成" % url)
threads = []
for url in url_list:
t = threading.Thread(target=download, args=(url,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("下载任务全部完成!")
上述代码使用了requests
模块下载了一个网页,并在控制台输出下载完成的信息。我们使用一个列表存储线程,遍历URL列表并为每个URL创建一个线程。在所有线程启动后,我们使用join
方法保证所有线程执行完成。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python线程详解 - Python技术站