千家信息网

Python多线程即相关理念分析

发表于:2025-02-09 作者:千家信息网编辑
千家信息网最后更新 2025年02月09日,这篇文章主要介绍"Python多线程即相关理念分析",在日常操作中,相信很多人在Python多线程即相关理念分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Pytho
千家信息网最后更新 2025年02月09日Python多线程即相关理念分析

这篇文章主要介绍"Python多线程即相关理念分析",在日常操作中,相信很多人在Python多线程即相关理念分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Python多线程即相关理念分析"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    一、什么是线程?

    线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程。车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线。所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

    总结进程与线程区别:

    '''进程:资源单位线程:执行单位线程才是真正干活的人,干活中需要的资源由线程所在进程提供每个进程肯定自带一个线程每个进程内可创建多个线程''''''开进程:    申请空间    拷贝代码    消耗资源大开线程:    同一个进程内创建多个线程,无需上述两种操作,消耗资源相对较小'''

    多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。

    二、开启线程的两种方式

    1、方式1

    from threading import Threadimport time# 方法一def task(name):    print('%s is running' % name)    time.sleep(1)    print('%s is over' % name)# 开启线程不需要在main下面执行代码,直接书写就可以# 但是习惯性的将启动命令写在main下面t = Thread(target=task, args=('egon',))t.start()  # 创建线程的开销非常小,几乎是代码一执行就已经创建了print('主')'''

    运行结果:
    egon is running

    egon is over
    '''

    2、方式2

    from threading import Threadclass MyThread(Thread):    def __init__(self, name):        # 重写了别人的方法,又不知道别人的方法里有啥,就调用父类的方法        super().__init__()        self.name = name    def run(self):        print('%s is running' % self.name)        time.sleep(1)        print('%s is over' % self.name)if __name__ == '__main__':    t = MyThread('egon')    t.start()    print('主')'''

    运行结果:
    egon is running

    egon is over
    '''

    三、线程对象的jion方法()

    看过我讲解进程文章的小伙伴想必都知道jion的功能,线程的jion方法于进程的jion方法功能类似-等待一个线程执行完毕后再执行下一个线程

    from threading import Threaddef task(name):    print('%s is running' % name)    time.sleep(1)    print('%s is over' % name)if __name__ == '__main__':    t=Thread(target=task,args=('egon',))    t.start()    t.join()# 主线程等待子线程运行结束后再执行    print('主')

    '''
    运行结果:
    egon is running
    egon is over

    '''

    补充一个知识点:同一个进程下的多个线程数据共享,下面为大家举一个简单的案例

    from threading import Threadmoney=100def task():    global money    money=66if __name__ == '__main__':    t=Thread(target=task,args=())    t.start()    print(money)

    # 结果:66

    四、 补充小案例

    from threading import Threadimport os,timedef task():    print('子 pid:',os.getpid())if __name__ == '__main__':    t=Thread(target=task,args=())    t.start()    print('主 pid:',os.getpid())    # 两个线程的pid号一样,说明在同一个进程下

    '''
    运行结果:
    子 pid: 13444
    主 pid: 13444
    '''

    # 这是个容易混淆的案例from threading import Thread,current_thread,active_countimport os,timedef task(n):    print('子',current_thread().name)    time.sleep(n) # 延长线程存活时间if __name__ == '__main__':    t=Thread(target=task,args=(1,))    t1=Thread(target=task,args=(1,))    t.start()    t1.start()    t.join()    # print('主',current_thread().name)# 获取线程名字    print(active_count()) # 统计当前活跃的进程数

    '''
    运行结果:
    子 Thread-1
    子 Thread-2
    1
    '''
    # 这里大家容易以为是3,其实运行后只有一个线程在活跃了,其它两个线程运行完后就停止运行了

    五、守护线程

    守护线程与守护进程的概念也类似,其实大家也能注意到,进程与线程有许多知识点即用法都是相通的,理解了一个另一个也是差不多的道理

    1、守护线程会随着主线程的结束而结束

    2、主线程运行结束后不会立刻结束,会等待所有的其它非守护线程结束后才会结束

    3、因为主线程的结束意味着所在进程的结束

    from threading import Threadimport timedef task(name):    print('%s is running'%name)    time.sleep(1)    print('%s is over'%name)if __name__ == '__main__':    t=Thread(target=task,args=('egon',))    t.daemon=True #将t设置为守护线程    t.start()    print('主')

    '''
    运行结果:
    egon is running

    '''

    # 稍微有点迷惑性的例子from threading import Threadimport timedef foo():    print('1234')    time.sleep(1)    print('end1234')def func():    print('5678')    time.sleep(3)    print('end5678')if __name__ == '__main__':    t1=Thread(target=foo,args=())    t2=Thread(target=func,args=())    t1.daemon=True # t1设为守护线程,t2为非守护线程    t1.start()    t2.start()    print('主......')

    '''
    运行结果:
    1234
    5678主......
    end1234
    end5678
    '''

    '''
    因主线程会等待非守护线程运行结束后在结束,
    所有主线程会等待t2(非守护线程)结束再结束,
    '''

    六、线程互斥锁

    多个线程操作同一份数据的时候,会出现数据错乱的问题

    针对上述问题,解决方式就是加锁处理

    from threading import  Thread,Lockimport timemoney=100mutex=Lock()def task():    global money    mutex.acquire()    tmp=money    time.sleep(0.1)# 模拟网络延迟    money=tmp-1    mutex.release()if __name__ == '__main__':    t_list=[]    for i in range(100):        t=Thread(target=task,args=())        t.start()        t_list.append(t)    for t in t_list:        t.join()    print(money)

    # 运行结果:0
    # 多个人操作同一份数据,数据错乱,加锁处理

    七、GTL-全局解释器

    相信学python的小伙伴都知道,python解释器其实有多个版本

    • Cpython

    • Jpython

    • Pypython

    但是普遍使用的都是Cpython解释器

    在Cpython解释器中GIL是一把互斥锁,用来阻止同一个进程下的多个线程的同时执行

    要注意同一进程下的多个线程无法利用多核优势!!!!

    想必大家心中也有不少疑惑:pyhon的多线程是不是一点用都没了呢????

    因为Cpython中的内存管理不是线程安全的。多线程并不是一无是处的,在遇到多IO操作的时候,多核的优势也会显示不出来,多进程与多线程的效率在该情况下差不了多少,而此时多进程相对浪费资源,多线程更加节省资源

    ps:内存管理就是垃圾回收机制:

    1、引用计数

    2、标记清除

    3、分带回收

    # GTL-全局解释器# 重点:1、GIL不是python的特点而是Cpython解释器的特点#      2、GIL是保证解释器级别的数据的安全#      3、GIL会导致同一个进程下的多个线程无法同时进行(即无法利用多核优势)#      4、针对不同的数据还是需要加不同的锁处理#      5、解释型语言的通病,同一个进程下多个线程无法利用多核优势

    多线程是否有用要看具体情况

    八、验证多线程与多线程运用场景

    # 计算密集型(CPU一直工作,也没有IO)(更适合多进程)from multiprocessing import Processfrom threading import Threadimport os,time# 多进程情况def work():    res=0    for i in range(0,10000000):        res*=iif __name__ == '__main__':    l=[]    print(os.cpu_count())# 获取当前计算机CPU核数    start_time=time.time()    for i in range(8):# 我计算机是8核        p= Process(target=work,args=())        p.start()        l.append(p)    for p in l:        p.join()    print(time.time()-start_time)

    '''
    运行结果:
    8
    2.0726492404937744
    '''

    # 多线程情况from multiprocessing import Processfrom threading import Threadimport os,timedef work():    res=0    for i in range(0,10000000):        res*=iif __name__ == '__main__':    l=[]    print(os.cpu_count())# 获取当前计算机CPU核数    start_time=time.time()    for i in range(8):# 我计算机是8核        t=Thread(target=work,args=())        t.start()        l.append(t)    for p in l:        p.join()    print(time.time()-start_time)

    '''
    运行结果:
    8
    3.5790603160858154
    '''

    # 显然可知:计算密集型更时候多进程

    # IO密集型(任务一直有IO)(多线程更合适)from multiprocessing import Processfrom threading import Threadimport os,time# 多线程def work():    time.sleep(1)if __name__ == '__main__':    l=[]    start_time=time.time()    for i in range(40):        t=Thread(target=work,args=())        t.start()        l.append(t)    for p in l:        p.join()    print(time.time()-start_time)# 运行结果:1.0205152034759521# 多进程from multiprocessing import Processfrom threading import Threadimport os,timedef work():    time.sleep(1)if __name__ == '__main__':    l=[]    start_time=time.time()    for i in range(40):        p= Process(target=work,args=())        # t=Thread(target=work,args=())        # t.start()        # l.append(t)        p.start()        l.append(p)    for p in l:        p.join()    print(time.time()-start_time)

    # 运行结果:5.927189588546753

    # 显然可知:IO密集型更适合多线程

    到此,关于"Python多线程即相关理念分析"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

    线程 进程 运行 多个 结果 资源 方法 解释 数据 解释器 车间 单位 理念 分析 优势 密集型 情况 方式 流水 流水线 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 无线网络安全密钥在哪里 软件开发合同职务 金融和软件开发哪个更好 腾讯rds数据库80个 云象网络技术有限公司怎么样 临沂澳莱软件开发有限公司 方舟服务器联机怎么调采集倍率 鲲鹏服务器什么时候上市 中专读计算机网络技术好吗 集团公司实行网络安全通报制度 数据库代理协议 汽车车载网络技术的课件 山东济南戴尔服务器代理客服电话 自动化测试需要数据库吗 数据库表重新编译 服务器存储设备采购清单 网络安全基本特性 山东通用软件开发报价表 软件开发后端指什么 mc魔方服务器 网络安全与防范ppt讲解 金山区推广软件开发信息中心 职业软件开发需要多少钱 方舟服务器联机怎么调采集倍率 数据库管理师考试试题 汇川科技软件开发 山东济南戴尔服务器代理客服电话 gorm 数据库备份 西湖论剑网络安全大会主论坛 我的世界服务器如何修改名称
    0