zoukankan      html  css  js  c++  java
  • python 并发编程之多线程

    一、线程概念

    把进程比作车间,

     车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线

          流水线的工作需要电源,电源就相当于cpu

      所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的最小执行单位。

    二、线程与进程的区别

    如果我们的软件是一个工厂,该工厂有多条流水线,流水线工作需要电源,电源只有一个即cpu(单核cpu)

    一个车间就是一个进程,一个车间至少一条流水线(一个进程至少一个线程)

    创建一个进程,就是创建一个车间(申请空间,在该空间内建至少一条流水线)

    而建线程,就只是在一个车间内造一条流水线,无需申请空间,随之创建开销小

    三、开启线程的两种方式

    1、例:

     1 # 第一种
     2 # from threading import Thread
     3 # import time
     4 
     5 # def task():
     6 #     print('开始')
     7 #     time.sleep(1)
     8 #     print('结束')
     9 #
    10 #
    11 # if __name__ == '__main__':
    12 #     t=Thread(target=task,) # 实例化得到一个对象
    13 #     t.start() # 对象.start()启动线程
    14 #     print('主')
    15 
    16 # 第二种,通过类继承的方式
    17 # from threading import Thread
    18 # import time
    19 # 
    20 # class MyThread(Thread):
    21 #     def run(self):
    22 #         print('开始')
    23 #         time.sleep(1)
    24 #         print('结束')
    25 # 
    26 # if __name__ == '__main__':
    27 #     t=MyThread()
    28 #     t.start()
    29 #     print('主')
    View Code

    四、线程对象join方法

     1 from threading import Thread
     2 
     3 import time
     4 def task(n):
     5     print('开始')
     6     time.sleep(n)
     7     print('结束')
     8 
     9 
    10 if __name__ == '__main__':
    11     t=Thread(target=task,args=(2,))
    12     t.start()
    13 
    14 
    15     t1=Thread(target=task,args=(3,))
    16     t1.start()
    17 
    18 
    19     t.join()  # 等待子进程执行结束
    20     t1.join()
    21     print('')
    View Code

    五、同一个线程下多个线程数据共享

    ```python
    from threading import Thread
    
    import time
    
    money = 99
    
    
    def task(n):
        global money
        money=n
        print('开始')
        # time.sleep(n)
        print('结束')
    
    
    if __name__ == '__main__':
        t = Thread(target=task, args=(2,))
        t.start()
    
        t1 = Thread(target=task, args=(66,))
        t1.start()
    
    
        t.join()
        t1.join()
        print(money)
        print('')
    
    ```
    View Code

    六、线程对象及其他方法

    1 线程t.name  t.getName()
    2 当前进程下有几个线程存活active_count
    3 t1.is_alive() 当前线程是否存活
    4 t1.ident  当作是线程id号

    七、守护线程

    from threading import Thread, current_thread,active_count
    import time
    import os
    
    
    def task(n):
        print('开始')
        time.sleep(n)
        # print('-----',active_count())
        print('结束')
    
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task,name='egon',args=(10,))
        # t1.daemon = True
        t1.setDaemon(True)
        t1.start()
    
        t2 = Thread(target=task,name='egon',args=(4,))
        t2.start()
    
        print('')
    View Code

    八、线程互斥锁

    ```python
    from threading import Thread,Lock
    import time
    import random
    
    money = 99
    
    
    def task(n,mutex):
        global money
        # 在修改数据的时候,枷锁
        mutex.acquire()
        temp = money
        time.sleep(0.1)
    
        money = temp - 1
        # 修改完以后,释放锁,其它线程就能再次抢到锁
        mutex.release()
    
    
    if __name__ == '__main__':
        ll=[]
        mutex=Lock()
        for i in range(10):
            t = Thread(target=task, args=(i,mutex))
            t.start()
            ll.append(t)
    
        for i in ll:
            i.join()
    
        print(money)
    
    ```

    九、

    GIL全局解释器锁理论
    ```python
    #1 python的解释器有很多,cpython,jpython,pypy(python写的解释器)
    #2 python的库多,库都是基于cpython写起来的,其他解释器没有那么多的库
    #3 cpython中有一个全局大锁,每条线程要执行,必须获取到这个锁
    #4  为什么会有这个锁呢?python的垃圾回收机制
    #5 python的多线程其实就是单线程
    #6 某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行
    # 7 总结:cpython解释器中有一个全局锁(GIL),线程必须获取到GIL才能执行,我们开的多线程,不管有几个cpu,同一时刻,只有一个线程在执行(python的多线程,不能利用多核优势)
    # 8 如果是io密集型操作:开多线程
    # 9如果是计算密集型:开多进程
    以上两句话,只针对与cpython解释器
    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    Oracle的数据伪列(ROWNUM)
    数据库的多表查询(详细案例分析)
    计算1至n的k次方的和
    位数对调(代码重构)
    java实现汉诺塔算法
    线程与进程详解
    java中properties的使用实例
    java中同步(synchronized)详解
    文件的拷贝操作
    文件的读取操作
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/13560061.html
Copyright © 2011-2022 走看看