多进程与多线程效率对比

  1. #
  2. # """
  3. #
  4. # 计算密集型
  5. # """
  6. # from threading import Thread
  7. # from multiprocessing import Process
  8. # import time
  9. #
  10. # a = 1
  11. # def task():
  12. # global a
  13. # for i in range(10000000):
  14. # a +=1
  15. # a * 10 / 2 - 3
  16. #
  17. # s = time.time()
  18. # #多线程
  19. # # t1 = Thread(target=task)
  20. # # t2 = Thread(target=task)
  21. # # t3 = Thread(target=task)
  22. #
  23. # if __name__ == '__main__':
  24. #
  25. # # 多进程
  26. # t1 = Process(target=task)
  27. # t2 = Process(target=task)
  28. # t3 = Process(target=task)
  29. # t1.start()
  30. # t2.start()
  31. # t3.start()
  32. #
  33. # t1.join()
  34. # t2.join()
  35. # t3.join()
  36. #
  37. # print(time.time() - s)
  38. #
  39. """
  40. IO型任务
  41. """
  42. from threading import Thread
  43. from multiprocessing import Process
  44. import time
  45. def task():
  46. # for i in range(10):
  47. with open(r"D:\脱产5期内容\day34\视频\1.线程理论.mp4",mode="rb")as f:
  48. while True:
  49. data = f.read(1024)
  50. if not data:
  51. break
  52. s = time.time()
  53. if __name__ == '__main__':
  54. # 多线程
  55. t1 = Thread(target=task)
  56. t2 = Thread(target=task)
  57. t3 = Thread(target=task)
  58. # 多进程
  59. # t1 = Process(target=task)
  60. # t2 = Process(target=task)
  61. # t3 = Process(target=task)
  62. t1.start()
  63. t2.start()
  64. t3.start()
  65. t1.join()
  66. t2.join()
  67. t3.join()
  68. print(time.time() - s)

GIL锁

  1. 什么是GIL
  2. 全局解释器锁,是加在解释器上的互斥锁
  3. 只存在于cpython解释器中
  4. python的内存回收管理机制,简称GC

GIL的加锁与解锁时机

  1. 加锁的时机:在调用解释器时立即加锁
  2. 解锁时机:
  3. 当前进程遇到IO或超时
  4. 为什么需要GIL
  5. 由于cpython的内存管理是非线程安全的,于是cpython就给解释器加了个锁,解决了安全问题,但是降低了效率,虽然有解决方 案,但是由于牵涉太多,一旦被修改,很多以前的基于GIL的程序都需要修改,所以变成了历史遗留问题
  6. GIL带来的问题
  7. 即使在多核处理器情况下,也无法真正的并行
  8. 先有多线程模块,有这个问题,所以后来有了多进程模块弥补这个问题
  9. 总结:
  10. 1.在单核情况下,无论是IO密集型还是计算密集,HIL都不会产生影响
  11. 2.如果是多核下,IO密集型会受到GIl的影响,但是很明显IO速度比计算速度慢
  12. 3.IO密集型多线程, 因为多线程开销小,节省资源,对于计算密集型,应该使用多进程,因为在cpytho中多线程是无法并行的

GIL与线程锁的区别

  1. from threading import Thread,Lock
  2. import time
  3. lock = Lock()
  4. a = 0
  5. def task():
  6. global a
  7. lock.acquire()
  8. temp = a
  9. time.sleep(0.01)
  10. a = temp + 1
  11. lock.release()
  12. ts = []
  13. for i in range(10):
  14. t1 = Thread(target=task)
  15. t1.start()
  16. ts.append(t1)
  17. for i in ts:
  18. i.join()
  19. print(a)
  20. GIL使用用于保护解释器相关的数据,解释器也是一段程序,肯定有其定义各种数据
  21. GIL并不能保证自己定义的数据的安全,所有一旦
  22. 多核cpu中,进程可以并行,线程不能并行

多线程TCP

  1. 客户端
  2. from threading import Thread
  3. import socket
  4. c = socket.socket()
  5. c.connect(("127.0.0.1",8989))
  6. def send_msg():
  7. while True:
  8. msg = input(">>>:")
  9. if not msg:
  10. continue
  11. c.send(msg.encode("utf-8"))
  12. send_t = Thread(target=send_msg)
  13. send_t.start()
  14. while True:
  15. try:
  16. data = c.recv(1024)
  17. print(data.decode("utf-8"))
  18. except:
  19. c.close()
  20. break
  21. 服务器端
  22. from concurrent.futures import ThreadPoolExecutor
  23. from threading import Thread
  24. import socket
  25. server = socket.socket()
  26. server.bind(("127.0.0.1",8989))
  27. server.listen()
  28. pool = ThreadPoolExecutor(3)
  29. def task(client):
  30. while True:
  31. try:
  32. data = client.recv(1024)
  33. if not data:
  34. client.close()
  35. break
  36. client.send(data.upper())
  37. except Exception:
  38. client.close()
  39. break
  40. while True:
  41. client,addr = server.accept()
  42. # t = Thread(target=task,args=(client,))
  43. # t.start()
  44. pool.submit(task,client)

线程池与进程池

  1. 池为容器,本质上就是一个存储进程或线程的列表
  2. from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
  3. from threading import active_count,current_thread
  4. import os,time
  5. # 创建线程池 指定最大线程数为3 如果不指定 默认为CPU核心数 * 5
  6. # pool = ThreadPoolExecutor(3)# 不会立即开启子线程
  7. #
  8. # print(active_count())
  9. #
  10. # def task():
  11. # print("%s running.." % current_thread().name)
  12. # time.sleep(1)
  13. #
  14. # #提交任务到线程池
  15. # for i in range(10):
  16. # pool.submit(task)
  17. #
  18. # 创建进程池 最大进程数为3 默认为cpu个数
  19. pool = ProcessPoolExecutor(3)# 不会立即开启子进程
  20. # time.sleep(10)
  21. def task():
  22. print("%s running.." % os.getpid())
  23. time.sleep(1)
  24. if __name__ == '__main__':
  25. # #提交任务到进程池
  26. for i in range(10):
  27. pool.submit(task) # 第一次提交任务时会创建进程 ,后续再提交任务,直接交给以及存在的进程来完成,如果没有空闲进程就等待
  28. # 与信号量的区别 ,信号量也是一种锁 适用于保证同一时间能有多少个进程或线程访问
  29. # 而线程/进程池,没有对数据访问进行限制仅仅是控制数量

同步与异步

  1. """
  2. 阻塞 非阻塞
  3. 程序遇到了IO操作,无法继续执行代码,叫做阻塞
  4. 程序没有遇到IO操作,正常执行中,就叫非阻塞
  5. 它们指的是程序的状态
  6. 就绪 运行 阻塞
  7. 就绪和阻塞给人的感觉就是卡主了
  8. 同步 异步
  9. 同步(调用/执行/任务/提交),发起任务后必须等待任务结束,拿到一个结果才能继续运行
  10. 异步 发起任务后不需要关系任务的执行过程,可以继续往下运行
  11. 异步效率高于同步
  12. 但是并不是所有任务都可以异步执行,判断一个任务是否可以异步的条件是,任务发起方是否立即需要执行结果
  13. 同步不等于阻塞 异步不等于非阻塞
  14. 当使用异步方式发起任务时 任务中可能包含io操作 异步也可能阻塞
  15. 同步提交任务 也会卡主程序 但是不等同阻塞,因为任务中可能在做一对计算任务,CPU没走
  16. """
  17. # 使用线程池 来执行异步任务
  18. from concurrent.futures import ThreadPoolExecutor
  19. import time
  20. pool = ThreadPoolExecutor()
  21. def task(i):
  22. time.sleep(1)
  23. print("sub thread run..")
  24. i += 100
  25. return i
  26. fs = []
  27. for i in range(10):
  28. f = pool.submit(task,i) # submit就是一异步的方式提交任务
  29. # print(f)
  30. # print(f.result()) # result是阻塞的 会等到这任务执行完成才继续执行 ,会异步变成同步
  31. fs.append(f)
  32. # 是一个阻塞函数,会等到池子中所有任务完成后继续执行
  33. pool.shutdown(wait=True)
  34. # pool.submit(task,1) # 注意 在shutdown之后 就不能提交新任务了
  35. for i in fs:
  36. print(i.result())
  37. print("over")

使用线程池 来发起异步任务

  1. 阻塞函数
  2. pool.shutdown()
  3. 同步不是阻塞,异步也不完全是非阻塞,也有可能阻塞

day36 GIL锁与线程池的更多相关文章

  1. GIL锁、进程池与线程池

    1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multip ...

  2. python GIL锁、进程池与线程池、同步异步

    一.GIL全局解释器锁 全局解释器锁 在CPython中,全局解释器锁(GIL)是一个互斥锁,它可以防止多个本机线程同时执行Python代码.之所以需要这个锁,主要是因为CPython的内存管理不是线 ...

  3. GIL锁、进程池与线程池、同步异步

    GIL锁定义 GIL锁:Global Interpreter Lock  全局解释器 本质上是一把互斥锁 官方解释: 在CPython中,这个全局解释器锁,也称为GIL,是一个互斥锁,防止多个线程在同 ...

  4. GIL全局解释器锁,线程池与进程池 同步异步,阻塞与非阻塞,异步回调

    GIL全局解释器锁 1.什么是GIL 官方解释:'''In CPython, the global interpreter lock, or GIL, is a mutex that prevents ...

  5. GIL、进/线程池、同/异步、阻/非阻塞

    1 GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点: 保证Cpython解释器内存管理 ...

  6. Java多线程总结(二)锁、线程池

    掌握Java中的多线程,必须掌握Java中的各种锁,以及了解Java中线程池的运用.关于Java多线程基础总结可以参考我的这篇博文Java多线程总结(一)多线程基础 转载请注明出处——http://w ...

  7. python网络编程--线程(锁,GIL锁,守护线程)

    1.线程 1.进程与线程 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率.很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观 ...

  8. 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)

    GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行的, ...

  9. 线程锁,threadinglocal,线程池,生产者消费者模型

    1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...

随机推荐

  1. 2018.4.27 python使用过的第三方库

    Flask flask-login flask-sqlalchemy flask-mail psutil lvm2py oss2 python-ldap pyudev pyOpenSSL urllib ...

  2. .Net调用Java带验证的WebService解决方法

    最近遇到了一个问题,需要通过验证用户名.密码去调用对方Java给出的WebService接口. 搜索了很多资料,没想到最终很简单就完了.... (捂脸 第一步:添加web引用 第二步:进行验证,并完成 ...

  3. 解决WPF中异常导致的程序Crash

    通常在WPF中出现异常,会导致程序Crash,即使把异常Throw出来,依旧会报错,解决方法只需在App.xaml.cs中进行处理即可,废话不说,代码如下: private int exception ...

  4. Flutter 知识点

    Flutter:一个移动应用开发框架,它使用 Dart.C++.Skia 开发,对外提供了完全不依赖系统平台的 Widget 的能力,只通过自绘图形的方式工作,具有极其优秀的跨平台性.目前已经支持了 ...

  5. asp.net core 基于角色的认证登陆

    一.登陆页面的Controller [Authorize(Roles = "Admin,SuperAdmin")] public class ManageController : ...

  6. # 20175227 2018-2019-2 《Java程序设计》第二周学习总结

    20175227 2018-2019-2 <Java程序设计>第二周学习总结 教材学习内容总结 1. 根据蓝墨云上的学习视频,自学第二.三章知识,并自行编译调试书上程序. 2. 第二章主要 ...

  7. 在Docker中监控Java应用程序的5个方法

    译者注:Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.通常情况下,监控的主要目的在于:减少宕机 ...

  8. Java异常学习总结二

    异常的处理方式 方式一:捕获异常(try-catch-finally) 捕获异常是通过三个关键词来实现的:try-catch-finally.用try来执行一段程序,如果出现异常,系统抛出一个异常,可 ...

  9. [UE4]Tile View

    一.Tile View也属于List View,Tile View以小方格的形式展示子控件. 二.Tile View.Entry Height.Tile View.Entry Width设置每个Til ...

  10. 从Tomcat的处理web请求分析Java的内存模型

    Tomcat作为一个java应用,同样是有主线程和子线程的.主线使用while(true)的方式一直循环,等待客户端来连接.一个客户端来了之后,就从线程池中拿一个线程来处理请求,如果没有配置线程池,就 ...