zoukankan      html  css  js  c++  java
  • python学习Day38--进程与线程

    一、回顾

    1、生产者消费者模型

      主要为了解决强耦合的问题

    2、队列 from multiprocessing import Queue

      先进先出,队列本身是安全的

      可连接的队列:from multiprocessing import JoinableQueue

      task_done( )  每消费一个数据,就返回一个标识

      join( )             接收task_done返回的标识,以便可以知道队列中的数据什么时候被消费完了

    3、管道(了解)

      本身不安全的

      队列 = 管道 + 锁

      from multiprocessing import Pipe

      con1,con2 = Pipe( )

      con1可以收发数据,con2也可以收发数据(全双工)

    4、多进程之间共享内存数据

      from multiprocessing import Manager,Value

    5、进程池

      from multiprocessing import Pool

      p.map(func,iterable)

      p.apply(func,args=( ))

      p.apply_async(func, args=( ),callback=None)

        close:不再接收新的任务,准备关闭

        join:等待进程池中的所有进程执行完任务

      池中的进程是守护进程,主进程的代码执行完毕,守护进程就结束了

      在进程池中的回调函数是主进程调用的,和子进程无关。

    二、线程

    1、线程的概念

      线程被称作轻量级的进程。 GIL:全局解释锁(只有Cpython解释器才有)

      计算机的执行单位以线程为单位,计算机的最小可执行是线程。

      进程是资源分配的基本单位。线程是可执行的基本单位,是可被调度的基本单位。

      线程不可以自己独立拥有资源。线程的执行,必须依赖于所属进程中的资源。

      线程又分为用户级线程和内核级线程:(了解)

        用户级线程:对于程序员来说的,这样的线程完全被程序员控制执行,调度。

        内核级线程:对于计算机内核来说的,这样的线程完全被内核控制调度。

    2、线程和进程的比较

      进程由:代码段、数据段、PCB组成

      线程由:代码段、数据段、TCB组成

    (1)初识线程

     1 # *******************初识线程**********************开始
     2 import threading
     3 from threading import Thread
     4 import time
     5 
     6 def func():
     7     print("这是一个子线程")
     8     time.sleep(2)
     9 
    10 if __name__ == '__main__':
    11     t = Thread(target=func,args=())
    12     t.start()
    13 # *******************初识线程**********************结束

    (2)线程与进程对比

      ① CPU切换进程要比CPU切换线程慢很多,在pyth中,如果IO操作过多的化话,使用多线程最好了。

     1 # *******************线程与进程法比较**********************开始
     2 from multiprocessing import Process
     3 from threading import Thread
     4 import time
     5 
     6 def func():
     7     pass
     8 
     9 if __name__ == '__main__':
    10     start = time.time()
    11     for i in range(100):
    12         p = Process(target=func)
    13         p.start()
    14     print("开100个进程的时间:",time.time()-start)
    15 
    16     start = time.time()
    17     for i in range(100):
    18         t = Thread(target=func)
    19         t.start()
    20     print("开100个线程的时间:", time.time() - start)
    21 # *******************线程与进程法比较**********************结束
    对比1

      ② 在同一个进程内,所有线程共享这个进程的pid,也就是说所有线程共享所属进程的所有资源和内存地址。、

     1 from multiprocessing import Process
     2 from threading import Thread
     3 import time,os
     4 
     5 def func(name):
     6     print("我是一个%s,我的pid是%s" % (name,os.getpid()))
     7 
     8 if __name__ == '__main__':
     9     print("我是main,我的的pid是:%s" % os.getpid())
    10     for i in range(10):
    11         p = Process(target=func,args=('进程',))
    12         p.start()
    13 
    14     for i in range(10):
    15         p = Thread(target=func,args=('线程',))
    16         p.start()
    对比3

      ③ 在同一个进程内,所有线程共享该进程的全局变量。

     1 # *******************线程与进程的对比3**********************开始
     2 from multiprocessing import Process
     3 from threading import Thread
     4 import time,os
     5 
     6 def func():
     7     global num
     8     num -= 1
     9 
    10 if __name__ == '__main__':
    11     num = 100
    12     t = Thread(target=func)
    13     t.start()
    14     time.sleep(1)
    15     print(num) # 99
    16 # *******************线程与进程的对比3**********************结束
    对比3

    (3)线程之间的数据安全问题

      因为有GIL锁的存在,在Cpython中,没有真正的线程并行。但是有真正的多进程并行。

      当你的任务是计算密集的情况下,使用多进程好。

      【总结】在Cpython中,IO密集用多线程,计算密集用多进程。

    3、死锁

    (1)什么是死锁?如下代码

     1 # *******************什么是死锁**********************开始
     2 from multiprocessing import Process
     3 from threading import Thread,Lock
     4 import time,os
     5 
     6 def man(l_tot,l_pap):
     7     l_tot.acquire()# 是男的获得厕所资源,把厕所锁上了
     8     print('alex在厕所上厕所')
     9     time.sleep(1)
    10     l_pap.acquire()# 男的拿纸资源
    11     print('alex拿到卫生纸了!')
    12     time.sleep(0.5)
    13     print('alex完事了!')
    14     l_pap.release()# 男的先还纸
    15     l_tot.release()# 男的还厕所
    16 
    17 def woman(l_tot,l_pap):
    18     l_pap.acquire()  # 女的拿纸资源
    19     print('小雪拿到卫生纸了!')
    20     time.sleep(1)
    21     l_tot.acquire()  # 是女的获得厕所资源,把厕所锁上了
    22     print('小雪在厕所上厕所')
    23     time.sleep(0.5)
    24     print('小雪完事了!')
    25     l_tot.release()  # 女的还厕所
    26     l_pap.release()  # 女的先还纸
    27 
    28 
    29 if __name__ == '__main__':
    30     l_tot = Lock()
    31     l_pap = Lock()
    32     t_man = Thread(target=man,args=(l_tot,l_pap))
    33     t_woman = Thread(target=woman,args=(l_tot,l_pap))
    34     t_man.start()
    35     t_woman.start()
    36 # *******************什么是死锁**********************结束

    (2)解决死锁问题——递归锁

     1 # *******************解决死锁**********************开始
     2 '''RLock是递归锁——是无止尽的锁,但是所有锁都有一个共同的钥匙'''
     3 
     4 from threading import Thread,RLock
     5 import time,os
     6 
     7 def man(l_tot,l_pap):
     8     l_tot.acquire()# 是男的获得厕所资源,把厕所锁上了
     9     print('alex在厕所上厕所')
    10     time.sleep(1)
    11     l_pap.acquire()# 男的拿纸资源
    12     print('alex拿到卫生纸了!')
    13     time.sleep(0.5)
    14     print('alex完事了!')
    15     l_pap.release()# 男的先还纸
    16     l_tot.release()# 男的还厕所
    17 
    18 def woman(l_tot,l_pap):
    19     l_pap.acquire()  # 女的拿纸资源
    20     print('小雪拿到卫生纸了!')
    21     time.sleep(1)
    22     l_tot.acquire()  # 是女的获得厕所资源,把厕所锁上了
    23     print('小雪在厕所上厕所')
    24     time.sleep(0.5)
    25     print('小雪完事了!')
    26     l_tot.release()  # 女的还厕所
    27     l_pap.release()  # 女的先还纸
    28 
    29 
    30 if __name__ == '__main__':
    31     l_tot = l_pap = RLock()
    32     t_man = Thread(target=man,args=(l_tot,l_pap))
    33     t_woman = Thread(target=woman,args=(l_tot,l_pap))
    34     t_man.start()
    35     t_woman.start()
    36 # *******************解决死锁**********************结束
    递归锁

     【小结——锁】

      递归锁:RLock( )可以有无止尽的锁,但是会有一把万能钥匙

      互斥所:Lock( )  一把钥匙配一把锁

      GIL:全局解释器锁,锁的是线程,是解释器上的一个锁,锁的是线程,意思是在同一时间只允许一个线程访问CPU。

    4、使用条件机制调度线程

      from threading import Thread, Condition

      Conditon( )涉及4个方法:

        acquire( ) # 加锁

        release( )# 解锁

        wait( ) # 是指给wait发一个信号,让wait变成不阻塞

        notify(int) # 是指给wait发一个信号,让wait变成不阻塞(int是指给多少wait发信号)

     1 # *******************Conditon**********************开始
     2 from threading import Condition,Thread
     3 import time
     4 
     5 def func(con,i):
     6     con.acquire()
     7     print(123)
     8     con.wait() # 线程执行到这里,会阻塞住,等待notify发送信号,来唤醒此线程
     9     print(456)
    10     con.release()
    11     print("第%s个线程开始执行了!" % i)
    12 
    13 if __name__ == '__main__':
    14     con = Condition()
    15     for i in range(10):
    16         t = Thread(target=func,args=(con,i))
    17         t.start()
    18 
    19     while 1:
    20         num = int(input("》》》"))
    21         con.acquire()
    22         con.notify(num) # 发送一个信号给num个正在阻塞在wait的线程,让这些线程正常执行
    23         con.release()
    24 # *******************Conditon**********************结束
    Conditon

    5、线程里的定时器

    1 # *******************定时器**********************开始
    2 from threading import Timer
    3 
    4 def func():
    5     print("开始执行了")
    6 
    7 Timer(3,func).start() # 3秒后执行func
    8 # *******************定时器**********************结束

    6、线程里的事件机制

      from threading import Event(与多进程的事件机制一样)

    7、线程里的信号量

      from threading import Semaphore(与多进程里的信号量一样)

    8、线程里的守护线程

      守护线程是根据主进程执行结束才结束

      守护线程不是根据主线程的代码执行结束而结束

      主线程会等待普通线程执行结束,再结束

      守护线程会等待主线程结束,再结束。

     1 # *******************守护线程**********************开始
     2 from threading import Thread
     3 import time
     4 
     5 def func():
     6     time.sleep(2)
     7     print(123)
     8 
     9 def func1():
    10     time.sleep(3)
    11     print(456)
    12 
    13 if __name__ == '__main__':
    14     t = Thread(target=func)
    15     t.daemon = True # 守护线程
    16     t.start()
    17     t1 = Thread(target=func1)
    18     t1.start()
    19 # *******************守护线程**********************结束
  • 相关阅读:
    获取设备的UUID
    关于获取基站信息总结
    【转】获取CID 和 LAC的方法
    js(javascript)与ios(Objective-C)相互通信交互
    ios面试题
    iOS 知识-常用小技巧大杂烩
    iOS时间格式的转换
    PresentViewController切换界面
    宏文件
    iOS使用NSMutableAttributedString 实现富文本(不同颜色字体、下划线等)
  • 原文地址:https://www.cnblogs.com/fengxb1213/p/12761879.html
Copyright © 2011-2022 走看看