欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python的多线程

程序员文章站 2024-03-23 18:12:10
...

什么是线程:

  • 线程也是一种多任务编程方法,可以利用计算机多核资源完成程序的并发执行。线程又被称为轻量级的进程。

线程的特征:

  • 线程是计算机多核分配的最小单位
  • 一个进程可以包含多个线程
  • 线程也是一个运行的过程,消耗计算机资源,多个线程共享进程的资源和空间
  • 线程的创建删除消耗的资源都要远远小于进程
  • 多个线程之间执行互不干扰
  • 线程也有自己的特有属性,比如指令集 ID

Python中使用threading模块创建线程

主要方法:

threading.Thread()

  • 功能:创建线程对象
  • 参数:name(线程名称,默认Thread-1),target(线程函数),args(元组,给线程函数位置传参),kwargs(字典,给线程函数键值传参)

t.start()

  • 功能:启动线程,自动运行线程函数

t.join([timeout])

  • 功能:回收线程
  • 参数(timeout):阻塞等待时间

线程对象属性:

t.is_alive()

  • 功能:查看线程状态

t.setName()

  • 功能:设置线程名称

t.getName() 或者 t.name

  • 功能:获取线程名称

threading.currentThread()

  • 功能:获取当前线程对象

t.daemon属性

  • 默认情况主线程退出不会影响分支线程执行,如果设置为True则分支线程随主线程退出

设置方法(两种):

  • t.daenon = True
  • t.setDaemon(True)

判断属性值
t.isDaemon()

注意: t.daenon要在start前设置,不能和join同用

多线程代码实现实例:

from threading import Thread, currentThread
from time import sleep 
import os 

a = 100

#线程函数
def test():
    global a
    a += 10
    # 获取当前线程的状态
    print("test is_alive:{}".format(currentThread().is_alive()))
    # 获取当前线程所在进程的pid
    print("{}:{}".format(currentThread().getName(), os.getpid()))

# 用来测试daemon属性的
def test3():
	print("进入线程test3...")
	# 阻塞等待10秒
	sleep(10)
	print("我是线程test3!")

#创建线程对象
t1 = Thread(name = "th1", target = test)
t2 = Thread(name = "th2", target = test)
t3 = Thread(target = test3)
t1.start()
t2.start()

# 设置t3线程随主线程退出而退出
t3.setDaemon(True) 
t3.start()

sleep(2)

# 主线程所在进程pid
print("main-thread:{}".format(os.getpid()))

# 修改线程名称
t1.setName("new-th1")
print("t1-new-name:"+t1.getName())

# 查看线程状态
print("t1 is_alive:{}".format(t1.is_alive()))
print("t2 is_alive:{}".format(t2.is_alive()))

# 只需要回收t1和t2
t1.join()
t2.join()

print("a = {}".format(a))

运行结果:

[email protected]:~/python/multithreading$ python3 thread_test.py 
test is_alive:True
th1:9233
test is_alive:True
th2:9233
进入线程test3...
main-thread:9233
t1-new-name:new-th1
t1 is_alive:False
t2 is_alive:False
a = 120

在这个实例中,一个主线程创建了三个子线程(t3是用来测试daemon属性的),发现可以通过子线程修改主线程中的全局变量a。同时我们发现,主线程和子线程的pid都是一样的,这说明,他们共用一个进程,即:一个进程中包含了多个线程。再看看daemon属性,t3设置daemon为True,我们发现,主线程执行完后,t3线程并没有执行完就退出了。

线程通信

  • 通信方法:多个线程共享进程的空间,所以线程间通信可以使用全局变量完成(比如上述实例中的a变量)。
  • 注意事项:线程间使用全局变量往往要同步互斥机制保证通信安全

重要!python线程的GIL问题(全局解释器锁)

  • 后果:一个解释器同一时刻只能解释执行一个线程,所以导致python线程效率低下。但是当遇到IO阻塞时线程会主动让出解释器,因此python线程更加适合高延迟的IO程序并发。

解决方法:

  • 若需要实现并行操作,尽量使用多进程
  • 尽量使用多种方案组合的方式进行并发操作,线程用作高延迟IO
相关标签: Python 多线程