• python学习(三十二)线程锁&守护线程&多进程


    1、线程锁

    如果多个线程同时要修改一个数据的时候,可能会把数据覆盖,这个时候就要在改数据的时候加锁,只同时有一个线程在改这个数据,改完后再解锁。

    在Python2里面要加锁,在Python3里面不用,因为Python3里面会自动加锁和解锁。

    在Python2里面加锁的代码如下:

    import threading,time
    num=1
    lock=threading.Lock() #申请一把锁
    def run():
        time.sleep(1)
        global num
        lock.acquire()  #加锁
        num+=1
        lock.release()   #解锁   #在python3里面可以不加,默认会加上的
    ts=[]
    for  i in range(50):
        t=threading.Thread(target=run)
        t.start()
        ts.append(t)
    [t.join() for t in ts]
    #如果主线程没有做等待(以上两句),那么最后打印的num值是1,因为打印num的时候,子线程因有sleep时间还没执行完
    print(num)

    2、守护线程

     把子线程设置为守护线程,那么主线程一旦结束,子线程不管有没有执行完也会结束

    import threading,time
    def run():
        time.sleep(3)
        print('hhh')
    
    for i in range(50):
        t=threading.Thread(target=run)
        t.setDaemon(True)  #把子线程设置成为守护线程
        t.start()
    print('运行完成')  #主线程执行完了,子线程也就结束了,所以只会打印这一句

    以上代码,本来在3秒后要输出hhh,结果因为主线程运行完后,还没到3秒,hhh还没打印,子线程也结束了,所以只输出运行完成

    如果以上代码主线程在输出运行完成后,等待3秒,那么子线程就可以执行

    import threading,time
    def run():
        time.sleep(3)
        print('hhh')
    
    for i in range(50):
        t=threading.Thread(target=run)
        t.setDaemon(True)  #把子线程设置成为守护线程
        t.start()
    print('运行完成')  #主线程执行完了,子线程也就结束了,所以只会打印这一句
    time.sleep(3)  #因为主线程在打印上一句后,等待了3秒,这时候子线程运行完了,所以子线程的内容也会打印

    3、多进程

    多进程多用于处理CPU密集型任务

    多线程多用于处理I/O密集型任务

    import multiprocessing,threading
    def my():
        print('哈哈哈哈')
    def run(num):
        for i in range(num):
            t=threading.Thread(target=my)
            t.start()
    if __name__=='__main__':
        for i in range(5):
            p=multiprocessing.Process(target=run,args=(6,)) #启动进程
            p.start()

    启动进程,每个进程有6个线程,总共5个进程,最后输出30次哈哈哈哈

    4、问题:为什么python的多线程不能利用多核CPU,但是在写代码的时候,多线程的确是在并发,而且还比单线程快

    原因:因为GIL,python只有一个GIL,运行python时,就要拿到这个锁才能执行,在遇到I/O 操作时会释放这把锁。
    如果是纯计算的程序,没有 I/O 操作,解释器会每隔100次操作就释放这把锁,让别的线程有机会 执行(这个次数可以通sys.setcheckinterval
    来调整)同一时间只会有一个获得GIL线程在跑,其他线程都处于等待状态
    1、如果是CPU密集型代码(循环、计算等),由于计算工作量多和大,计算很快就会达到100,然后触发GIL的释放与在竞争,多个线程来回切换损耗资源,
    所以在多线程遇到CPU密集型代码时,单线程会比较快
    2、如果是IO密集型代码(文件处理、网络爬虫),开启多线程实际上是并发(不是并行),IO操作会进行IO等待,线程A等待时,自动切换到线程B,
    这样就提升了效率 

     

  • 相关阅读:
    编程算法
    2048小游戏主要算法实现
    Spring 计时器 @Scheduled cron 含义
    jQuery Validate Ajax 验证
    jQuery Validate 使用
    Java 两个整数相除保留两位小数,将小数转化为百分数
    mybatis+mysql返回插入的主键,参数只是提供部分参数
    微信 创建自定义菜单 向微信发起的post请求
    JSON.parse()和JSON.stringify()
    前台JSON字符串,spring mvc controller也接收字符串
  • 原文地址:https://www.cnblogs.com/emilyliu/p/9112471.html
Copyright © 2020-2023  润新知