Python进阶基础学习(多线程)
Python进阶学习笔记(一)
threading模块
threading.thread(target = (函数)) 负责定义子线程对象
threading.enumerate() 负责查看子线程对象
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import time import threading def sing(): for i in range ( 5 ): print ( '-----唱歌-----' ) time.sleep( 1 ) def dance(): for i in range ( 5 ): print ( '-----跳舞-----' ) time.sleep( 1 ) def main(): t1 = threading.Thread(target = sing) #子线程1 t2 = threading.Thread(target = dance) #子线程2 t1.start() t2.start() while True : print (threading. enumerate ()) if len (threading. enumerate ()) = = 1 : break time.sleep( 1 ) if __name__ = = '__main__' : main() |
补充:
线程的调度是随机的,主线程如果在子线程之前GG,你们子线程也GG
threading.thread()不会创建线程,只有调用其实例.start()之后才会创建线程
通过类来创建线程
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import threading import time class Person(threading.Thread): def run( self ) - > None : for i in range ( 3 ): print ( 'aaa' + self .name) time.sleep( 1 ) if __name__ = = '__main__' : p = Person() p.start() for i in range ( 3 ): print ( 'bbb' ) time.sleep( 1 ) |
补充:
threading.thread是一个类,通过继承并且override run函数,即可声明进程
多线程共享全局变量
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import threading import time num = 100 def test1(): global num num + = 1 print (num) def test2(): print (num) def main(): t1 = threading.Thread(target = test1) t2 = threading.Thread(target = test2) t1.start() time.sleep( 1 ) test2() if __name__ = = '__main__' : main() |
若创建线程是需要带参数,则是用args
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | num = [ 1 , 1 , 2 , 3 ] def test1(args): args.append( 'hhs' ) print (args) def main(): t1 = threading.Thread(target = test1,args = (num,)) t1.start() print (num) if __name__ = = '__main__' : main() |
补充:args后边传的是一个元组,少了逗号会报错
多线程共享全局变量出现的问题
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import threading import time g_num = 0 def count1(n): global g_num for i in range (n): g_num + = 1 def count2(n): global g_num for i in range (n): g_num + = 1 def main(): t1 = threading.Thread(target = count1,args = ( 100000 ,)) t2 = threading.Thread(target = count2, args = ( 100000 ,)) t1.start() t2.start() time.sleep( 2 ) print ( '正常num为200000,实际num为%d' % g_num) if __name__ = = '__main__' : main() |
补充:输出结果为:175586,与正常结果不相同
解析问题:
1.cpu是一句句执行的
2.若把g_num += 1解析成很多句,如果线程1只执行1-2句,第三句还没赋值回去,就调用了线程2,则会出现相加的结果不等于预期的结果
互斥锁threading.Lock()
用于解决上面共享全局变量的问题
变量名.acquire() 上锁
变量名.release() 解锁
给要执行的代码上锁,自己运行的时候别的线程无法运行
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import threading import time num = 0 mutex = threading.Lock() def count1(n): global num for i in range (n): mutex.acquire() num + = 1 mutex.release() def count2(n): global num for i in range (n): mutex.acquire() num + = 1 mutex.release() def main(): t1 = threading.Thread(target = count1,args = ( 100000 ,)) t2 = threading.Thread(target = count2, args = ( 100000 ,)) t1.start() t2.start() time.sleep( 2 ) print ( '正常num为200000,实际num为%d' % num) if __name__ = = '__main__' : main() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!