Skip to content

线程

  • 线程是进程的一个实体,是进程的一部分,进程可以有多个线程。
  • 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来处理