zoukankan      html  css  js  c++  java
  • Python多线程的理解和使用(一)Threading中join()函数的理解

    1. 多线程的概念

    多线程类似于同时执行多个不同程序,多线程运行有如下优点:

    使用线程可以把占据长时间的程序中的任务放到后台去处理。
    用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度 
    程序的运行速度可能加快
    在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
    线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

    每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。

    指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。

    线程可以被抢占(中断)。
    在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) -- 这就是线程的退让。
     

    2. Threading 多进程的使用案例:join()函数的理解

         通过以下实例可以get到join()函数的作用:如果thread是某个子线程,则调用thread.join()的作用是确保thread子线程执行完毕后才能执行下一个线程。下面第一个例子中没有调用join()函数,故没有这个限制,所有线程执行顺序都不定。

         第二个例子中在每个子线程启动start()后马上调用了join()函数,这就确保了对于每一个子线程,必须等它执行完毕后才能执行下一个程序,故子线程是按顺序执行的,且主线程中的print()方法是在所有的子线程执行完毕后才执行。

        第三个例子中,对于子线程启动start()后没有马上调用join()函数,故子线程的执行顺序是不确定的,但是主线程中的print()前调用了每个子线程的join()函数,故print()要在所有的子线程执行完毕后才能执行。

    (1)没有使用join()函数,线程执行顺序不定,主线程可能在所有子线程执行完之前就执行了

    import threading
    import time

    def test(p):
    time.sleep(0.001)
    print(p)

    ts = []

    for i in range(15):
    # target指定线程要执行的代码,args指定该代码的参数
    th = threading.Thread(target=test, args=[i])
    ts.append(th)

    for i in ts:
    i.start()

    print("it is end !")



    0
    1
    it is end !
    4
    2
    3
    5
    (2)修改部分代码如下:每次启动子线程后,调用一次join()函数,可以看出线程按顺序执行,且主线程在所有子线程执行完之              后才执行。

    for i in ts:
    i.start()
    # 此处的join函数子线程按顺序执行,即i线程跑完后才能继续跑下一个线程
    i.join()


    print("it is end !")



    0
    1
    2
    3
    4
    5
    it is end !
    (3)修改部分代码如下:可以看出子线程执行顺序不定,但是主线程是在所有子线程执行完毕之后才执行的。

    for i in ts:
    i.start()

    # 此处的join函数使子线程全部跑完再继续往下跑子线程
    for i in ts:
    i.join()

    print("it is end !")


    1
    0
    4
    5
    2
    3
    it is end !
     

    3. 全局锁

    (1)全局锁(GIL)是一个很重要的概念。

    在任意一个指定的时间,有且只有一个线程在运行 -》 python是线程安全的

    (2)io操作经常用到多线程,如在修改某个文档时,其他线程是不能进来干扰的。

        a. 加锁:acquire , 释放锁:release,   有加锁就一定要释放锁

    (3).rlock 可重入锁: 如果前面忘记了release释放锁,正常是无法再获取锁的,rlock可实现再获取锁。

    (4)实例:mlock.acquire()和mlock.release()之间的代码是不间断执行的,不会被其他线程干扰。

    import threading

    mlock = threading.Lock()
    lst = list(range(20))

    def change():
    global lst
    # mlock.acquire() # 加锁
    lst = [i+1 for i in lst]
    lst = [i*2 for i in lst]
    # mlock.release() #释放锁

    print(lst)

    for i in range(6):
    d = threading.Thread(target=change)
    d.start()


    [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]
    [6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82]
    [14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 142, 150, 158, 166]
    [30, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254, 270, 286, 302, 318, 334]
    [62, 94, 126, 158, 190, 222, 254, 286, 318, 350, 382, 414, 446, 478, 510, 542, 574, 606, 638, 670]
    [126, 190, 254, 318, 382, 446, 510, 574, 638, 702, 766, 830, 894, 958, 1022, 1086, 1150, 1214, 1278,  1342]
    ---------------------
    作者:zhuzuwei
    来源:CSDN
    原文:https://blog.csdn.net/zhuzuwei/article/details/80927554
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    [LeetCode]513 Find Bottom Left Tree Value(BFS)
    [LeetCode]71 Simplify Path(模拟)
    [LeetCode]338 Counting Bits(dp,lowbit)
    [LeetCode]419 Battleships in a Board(暴力,dfs)
    [POJ1568]Find the Winning Move(极大极小搜索,alpha-beta剪枝,特判)
    计蒜客 18487.Divisions-大数的所有因子个数-Miller_Rabin+Pollard_rho-超快的(大数质因解+因子个数求解公式) (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 F)
    计蒜客 18488.Extreme Sort (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 E)
    计蒜客 28319.Interesting Integers-类似斐波那契数列-递推思维题 (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 I)
    计蒜客 28317.Growling Gears-一元二次方程的顶点公式 (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 G)
    计蒜客 28315.Excellent Engineers-线段树(单点更新、区间最值) (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E)
  • 原文地址:https://www.cnblogs.com/chen-huan/p/10663881.html
Copyright © 2011-2022 走看看