多线程 threading 模块创建线程创建自己的线程类线程通信线程同步互斥方法线程锁 @需要了解!!!
多线程
什么是线程?
线程也是一种多任务的编程方法, 可以利用计算机多核资源完成程序的并发运行.
线程又被称为轻量级进程
线程的特征
线程是计算机多核分配的最小单位
一个进程可以包含多个线程
线程也是一个运行的过程, 消耗计算机资源, 多个线程共享进程的资源和空间
线程的创建删除消耗的资源都远远比进程小
多个线程之间执行互不干扰
线程也有自己的特有属性, 比如指令集 ID
threading 模块创建线程
t=threading.Thread()
功能: 创建线程对象
参数
name: 线程名称, 如果为空则为默认值, Tread-1,Tread-2,Tread-3
target: 线程函数
args: 元组, 给线程函数按照位置传参
kwargs: 字典, 给县城函数按照键值传参
t.start(): 启动线程, 自动运行线程函数
t.join([timeout]): 回收进程
t.is_alive(): 查看线程状态
t.name(): 查看线程名称
t.setName(): 设置线程名称
t.daemon 属性: 默认主线成退出不影响分支线程继续执行, 如果设置为 True 则分支线程随着主线程一起退出
设置方法
- t.daemon = True
- t.setDaemon(Ture)
- #!/usr/bin/env python3
- from threading import Thread
- from time import sleep
- import os
- # 创建线程函数
- def music():
- sleep(2)
- print("分支线程")
- t = Thread(target = music)
- # t.start() # ******************************
- print("主线程结束 ---------")
- '''没有设置的打印结果
- 主线程结束 ---------
- 分支线程
- '''
- '''设置为 True 打印结果
- 主线程结束 ---------
- '''
threading.currentThread: 获取当前线程对象
@此处代码示意子线程共享同一个进程内的变量
- #!/usr/bin/env python3
- from threading import Thread
- from time import sleep
- import os
- # 创建线程函数
- def music():
- global a
- print("a=",a)
- a = 10000
- for i in range(5):
- sleep(1)
- print("1212")
- a = 1
- t = Thread(target = music)
- t.start()
- t.join()
- print("主线程的 a =",a)
创建自己的线程类
考察点: 类的使用, 调用父类的__init__方法, 函数 * 传参和 ** 传参
- from threading import Thread
- import time
- class MyThread(Thread):
- name1 = 'MyThread-1'
- def __init__(self,target,args=(), kwargs={}, name = 'MyThread-1'):
- super().__init__()
- self.name = name
- self.target = target
- self.args = args
- self.kwargs = kwargs
- def run(self):
- self.target(*self.args,**self.kwargs)
- def player(song,sec):
- for i in range(2):
- print("播放 %s:%s"%(song,time.ctime()))
- time.sleep(sec)
- t =MyThread(target = player, args = ('亮亮',2))
- t.start()
- t.join()
线程通信
通信方法: 由于多个线程共享进程的内存空间, 所以线程间通信可以使用全局变量完成
注意事项: 线程间使用全局变量往往要同步互斥机制保证通信的安全
线程同步互斥方法
event
e = threading.Event(): 创建事件对象
e.wait([timeout]): 设置状态, 如果已经设置, 那么这个函数将阻塞, timeout 为超时时间
e.set: 将 e 变成设置状态
e.clear: 删除设置状态
- import threading
- from time import sleep
- def fun1():
- print("bar 拜山头")
- global s
- s = "天王盖地虎"
- def fun2():
- sleep(4)
- global s
- print("我把限制解除了")
- e.set() # 解除限制, 释放资源
- def fun3():
- e.wait() # 检测限制
- print("说出口令")
- global s
- if s == "天王盖地虎":
- print("宝塔镇河妖, 自己人")
- else:
- print("打死他")
- s = "哈哈哈哈哈哈"
- # 创建同步互斥对象
- e = threading.Event()
- # 创建新线程
- f1 = threading.Thread(target = fun1)
- f3 = threading.Thread(target = fun3)
- f2 = threading.Thread(target = fun2)
- # 开启线程
- f1.start()
- f3.start()
- f2.start()
- # 准备回收
- f1.join()
- f3.join()
- f2.join()
线程锁
lock = threading.Lock()
: 创建锁对象
lock.acquire(): 上锁
lock.release(): 解锁
也可以用过 with 来上锁
- with lock:
- ...
- ...
@需要了解!!!
Python 线程的 GIL 问题(全局解释器):
python---->支持多线程 ---->同步互斥问题 ---->加锁解决 ---->超级锁 (给解释器加锁)----> 解释器同一时刻只能解释一个线程 --->导致效率低下
后果:
一个解释器同一时刻只能解释执行一个线程, 所以导致 Python 线程效率低下, 但是当遇到 IO 阻塞时线程会主动让出解释器, 因此 Pyhton 线程更加适合高延迟的 IO 程序并发
解决方案
尽量使用进程完成并发(和没说一样)
不适当用 C 解释器 (用 C# ,JAVA)
尽量使用多种方案组合的方式进行并发操作, 线程用作高延迟 IO
来源: https://www.cnblogs.com/BanL/p/9642471.html