经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python3 » 查看文章
Python 3 线程模型,进程模型记录
来源:cnblogs  作者:xuyaowen  时间:2019/10/21 9:01:12  对本文有异议

最近需要使用 python3 多线程处理大型数据,顺道探究了一下,python3 的线程模型的情况,下面进行简要记录;

多线程运行的优点:

  • 使用线程可以把程序中占用时间较长的任务放到后台去处理;
  • 用户界面可以更加吸引人,并且不阻塞界面的运行;
  • 程序运行的速度可以更快;
  • 充分利用CPU多核的特征进行处理;

内核线程:由操作系统内核创建和撤销;

用户线程:不需要内核支持在用户程序中实现的线程;

Python3 中的多线程:

  • _thread 提供了一些原始的api 用于写多线程程序;
  • threading 提供了更加便利的接口
  • 两者都是python3内置的线程模块
  1. #!/usr/bin/env python
  2. import _thread
  3. def print_time( threadName, delay):
  4. print (threadName)
  5. count = 0
  6. while 1:
  7. pass
  8. count += 1
  9. try:
  10. _thread.start_new_thread( print_time, ("Thread-1", 1, ) )
  11. _thread.start_new_thread( print_time, ("Thread-2", 2, ) )
  12. _thread.start_new_thread( print_time, ("Thread-3", 2, ) )
  13. _thread.start_new_thread( print_time, ("Thread-4", 2, ) )
  14. _thread.start_new_thread( print_time, ("Thread-5", 2, ) )
  15. _thread.start_new_thread( print_time, ("Thread-6", 2, ) )
  16. _thread.start_new_thread( print_time, ("Thread-7", 2, ) )
  17. _thread.start_new_thread( print_time, ("Thread-8", 2, ) )
  18. _thread.start_new_thread( print_time, ("Thread-9", 2, ) )
  19. _thread.start_new_thread( print_time, ("Thread-10", 2, ) )
  20. _thread.start_new_thread( print_time, ("Thread-11", 2, ) )
  21. _thread.start_new_thread( print_time, ("Thread-12", 2, ) )
  22. _thread.start_new_thread( print_time, ("Thread-13", 2, ) )
  23. _thread.start_new_thread( print_time, ("Thread-14", 2, ) )
  24. _thread.start_new_thread( print_time, ("Thread-15", 2, ) )
  25. except:
  26. print ("Error: can't start thread!")
  27. while 1:
  28. pass
_thread测试
  1. #!/usr/bin/env python3
  2. import threading
  3. import time
  4. exitFlag = 0
  5. class myThread (threading.Thread):
  6. def __init__(self, threadID, name, counter):
  7. threading.Thread.__init__(self)
  8. self.threadID = threadID
  9. self.name = name
  10. self.counter = counter
  11. def run(self):
  12. print ("start" + self.name)
  13. print_time(self.name, self.counter, 5)
  14. print ("exit" + self.name)
  15. def print_time(threadName, delay, counter):
  16. while counter:
  17. if exitFlag:
  18. threadName.exit()
  19. time.sleep(delay)
  20. print ("%s: %s" % (threadName, time.ctime(time.time())))
  21. counter -= 1
  22. thread1 = myThread(1, "Thread-1", 1)
  23. thread2 = myThread(2, "Thread-2", 2)
  24. thread1.start()
  25. thread2.start()
  26. thread1.join()
  27. thread2.join()
  28. print ("exit!")
threading测试

python 的多线程 threading 有时候并不是特别理想. 最主要的原因是就是, Python 的设计上, 有一个必要的环节, 就是 Global Interpreter Lock (GIL). 这个东西让 Python 还是一次性只能处理一个东西:

尽管Python完全支持多线程编程, 但是解释器的C语言实现部分在完全并行执行时并不是线程安全的。 实际上,解释器被一个全局解释器锁保护着,它确保任何时候都只有一个Python线程执行。 GIL最大的问题就是Python的多线程程序并不能利用多核CPU的优势 (比如一个使用了多个线程的计算密集型程序只会在一个单CPU上面运行); 如果要进行利用python的多进程形式,可以使用python的 multiprocessing 编程模型包;

GIL只会影响到那些严重依赖CPU的程序(比如计算型的)。 如果你的程序大部分只会涉及到I/O,比如网络交互,那么使用多线程就很合适, 因为它们大部分时间都在等待;

  1. import threading
  2. from queue import Queue
  3. import copy
  4. import time
  5. def job(l, q):
  6. res = sum(l)
  7. q.put(res)
  8. def multithreading(l):
  9. q = Queue()
  10. threads = []
  11. for i in range(4):
  12. t = threading.Thread(target=job, args=(copy.copy(l), q), name='T%i' % i)
  13. t.start()
  14. threads.append(t)
  15. [t.join() for t in threads]
  16. total = 0
  17. for _ in range(4):
  18. total += q.get()
  19. print(total)
  20. def normal(l):
  21. total = sum(l)
  22. print(total)
  23. if __name__ == '__main__':
  24. l = list(range(1000000))
  25. s_t = time.time()
  26. normal(l*4)
  27. print('normal: ',time.time()-s_t)
  28. s_t = time.time()
  29. multithreading(l)
  30. print('multithreading: ', time.time()-s_t)
GIL测试
  1. #!/usr/bin/env python
  2. import multiprocessing as mp
  3. import threading as td
  4. def job(a,b):
  5. while 1:
  6. pass
  7. t1 = td.Thread(target=job,args=(1,2))
  8. t2 = td.Thread(target=job,args=(1,2))
  9. t3 = td.Thread(target=job,args=(1,2))
  10. t4 = td.Thread(target=job,args=(1,2))
  11. t5 = td.Thread(target=job,args=(1,2))
  12. t6 = td.Thread(target=job,args=(1,2))
  13. t7 = td.Thread(target=job,args=(1,2))
  14. t8 = td.Thread(target=job,args=(1,2))
  15. t9 = td.Thread(target=job,args=(1,2))
  16. t10 = td.Thread(target=job,args=(1,2))
  17. t11 = td.Thread(target=job,args=(1,2))
  18. t12 = td.Thread(target=job,args=(1,2))
  19. t13 = td.Thread(target=job,args=(1,2))
  20. t14 = td.Thread(target=job,args=(1,2))
  21. t15 = td.Thread(target=job,args=(1,2))
  22. t16 = td.Thread(target=job,args=(1,2))
  23. # p1 = mp.Process(target=job,args=(1,2))
  24. # p2 = mp.Process(target=job,args=(1,2))
  25. # p3 = mp.Process(target=job,args=(1,2))
  26. # p4 = mp.Process(target=job,args=(1,2))
  27. # p5 = mp.Process(target=job,args=(1,2))
  28. # p6 = mp.Process(target=job,args=(1,2))
  29. # p7 = mp.Process(target=job,args=(1,2))
  30. # p8 = mp.Process(target=job,args=(1,2))
  31. # p9 = mp.Process(target=job,args=(1,2))
  32. # p10 = mp.Process(target=job,args=(1,2))
  33. # p11 = mp.Process(target=job,args=(1,2))
  34. # p12 = mp.Process(target=job,args=(1,2))
  35. # p13 = mp.Process(target=job,args=(1,2))
  36. # p14 = mp.Process(target=job,args=(1,2))
  37. # p15 = mp.Process(target=job,args=(1,2))
  38. # p16 = mp.Process(target=job,args=(1,2))
  39. t1.start()
  40. t2.start()
  41. t3.start()
  42. t4.start()
  43. t5.start()
  44. t6.start()
  45. t7.start()
  46. t8.start()
  47. t9.start()
  48. t10.start()
  49. t11.start()
  50. t12.start()
  51. t13.start()
  52. t14.start()
  53. t15.start()
  54. t16.start()
  55. # p1.start()
  56. # p2.start()
  57. # p3.start()
  58. # p4.start()
  59. # p5.start()
  60. # p6.start()
  61. # p7.start()
  62. # p8.start()
  63. # p9.start()
  64. # p10.start()
  65. # p11.start()
  66. # p12.start()
  67. # p13.start()
  68. # p14.start()
  69. # p15.start()
  70. # p16.start()
  71. t1.join()
  72. t2.join()
  73. t3.join()
  74. t4.join()
  75. t5.join()
  76. t6.join()
  77. t7.join()
  78. t8.join()
  79. t9.join()
  80. t10.join()
  81. t11.join()
  82. t12.join()
  83. t13.join()
  84. t14.join()
  85. t15.join()
  86. t16.join()
  87. # p1.join()
  88. # p2.join()
  89. # p3.join()
  90. # p4.join()
  91. # p5.join()
  92. # p6.join()
  93. # p7.join()
  94. # p8.join()
  95. # p9.join()
  96. # p10.join()
  97. # p11.join()
  98. # p12.join()
  99. # p13.join()
  100. # p14.join()
  101. # p15.join()
  102. # p16.join()
跑满你的CPU process vs thread (以16线程CPU为例)

使用python multiprocess 包能够发挥多核CPU并行处理能力

  • multiprocess 接口和threading 使用的接口一样;

并发控制:

  • 进程锁: mp.Lock(), mp.acquire(), mp.release()
  • 线程锁: td.Lock(), td.acquire(), td.release() 
  • python 为了提高可用性,保证了multiprocessing 和 threading 中,大多数接口使用都是相同的,较为方便;
  • 多cpu之间,通过共享内存交流;mp.Value('i', 0)  
  • 输出队列:mp.Queue() 而 线程之间可以共享内存,可以直接使用 from queue import Queue 来进行引入队列进行使用;

保持更新,转载请注明出处,更多内容请关注cnblogs.com/xuyaowen;

参考链接:

https://morvanzhou.github.io/tutorials/python-basic/threading/5-GIL/ 

https://python3-cookbook.readthedocs.io/zh_CN/latest/c12/p09_dealing_with_gil_stop_worring_about_it.html  (Python Cookbook 3rd Edition Documentation)

https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/2-add/ 

原文链接:http://www.cnblogs.com/xuyaowen/p/Python3-thread-model.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号