Appearance
线程
- 线程是进程的一个实体,是进程的一部分,进程可以有多个线程。
threading模块提供了线程的相关功能。
优点
- 线程的创建和销毁比进程更快。
- 线程的切换比进程的切换更快。
- 线程可以并发执行,提高了程序的效率。
- 线程可以共享进程的资源,如内存、文件等。
- 线程可以独立执行,不影响其他线程的执行。
- 线程可以暂停执行,等待其他线程执行完毕。
缺点
- 线程的执行顺序是由操作系统的线程调度器来控制的,不能保证线程的执行顺序。
Thread 类
- 基于
threading模块Thread类管理线程的target线程要执行的目标函数args目标函数的参数kwargs目标函数的关键字参数name线程的名称daemon线程是否为守护线程
常用方法
start()启动线程join()等待线程执行完毕is_alive()判断线程是否执行完毕getName()获取线程的名称setName()设置线程的名称daemon设置线程是否为守护线程
线程管理
python
from threading import Thread
from time import sleep
ticket = 5
def task1():
global ticket
while ticket > 0:
ticket -= 1
print("task1 ticket:", ticket)
sleep(1)
def task2():
global ticket
while ticket < 3:
ticket += 1
print("task2 ticket:", ticket)
sleep(1)
if __name__ == '__main__':
p1 = Thread(target = task1, args = ())
p2 = Thread(target = task2, args = ())
p1.start() # 先执行减法器 4,3,2,1,0
p2.start() # 后执行加法器 1,2,3
p1.join() # 等待减法器执行完毕
p2.join() # 等待加法器执行完毕
print("main ticket:", ticket) # 3 线程中 变量是共享的锁
- python 线程默认加锁的,但是当系统资源达到一定程度时会自动解锁。
Lock类提供了线程的锁功能,用于保护线程中的共享资源。Lock类的常用方法:acquire()获取锁release()释放锁
python
from threading import Thread, Lock
ticket = 5
lock = Lock()
def task1():
lock.acquire()
global ticket
while ticket > 0:
ticket -= 1
print("task1 ticket:", ticket)
lock.release()
def task2():
lock.acquire()
global ticket
while ticket < 3:
ticket += 1
print("task2 ticket:", ticket)
lock.release()
if __name__ == '__main__':
p1 = Thread(target = task1)
p2 = Thread(target = task2)
p1.start()
p2.start()
p1.join()
p2.join()
print("main ticket:", ticket) # 3 线程中 变量是共享的死锁
- 死锁是指两个或多个线程同时等待对方释放资源,导致程序无法继续执行。
- 死锁的原因是线程中的锁是不可重入的,即一个线程获取到锁后,其他线程无法获取到锁,导致死锁。
- 死锁的解决方法是避免死锁,如使用
Lock类的acquire()方法的timeout参数,设置超时时间,避免死锁。
python
from threading import Lock
lock = Lock()
lock.acquire(timeout = 5) # 超时时间为5秒,超时锁住的代码不会执行
# 代码块
lock.release()适应场景
- 耗时操作推荐使用线程,如文件读写、数据库操作、数据采集等。
注意事项
- 线程中变量是共享的,但线程执行顺序不确定,导致数据是不安全的,所以需要
Lock来处理
