多进程实现TCP服务端并发

  1. 服务端:
  2. import socket
  3. from multiprocessing import Process
  4. def get_server():
  5. server = socket.socket()
  6. server.bind(('127.0.0.1',8088))
  7. server.listen(5)
  8. return server
  9. def get_talk(sock):
  10. while True:
  11. data = sock.recv(1024)
  12. print(data.decode('utf8'))
  13. sock.send(data.upper())
  14. if __name__ == '__main__':
  15. server = get_server()
  16. while True:
  17. sock, addr = server.accept()
  18. # 开设多进程 去聊天
  19. p = Process(target=get_talk, args=(sock,))
  20. p.start()
  21. 客户端:
  22. import socket
  23. client = socket.socket()
  24. client.connect(('127.0.0.1',8088))
  25. while True:
  26. client.send(b'hello baby')
  27. data = client.recv(1024)
  28. print(data)

互斥锁代码实操

  1. 锁:建议只加载操作数据的部分 否则整个程序的效率会极低
  2. from multiprocessing import Process,Lock
  3. import time
  4. import json
  5. import random
  6. def search(name):
  7. with open(r'data.json','r',encoding='utf8')as f:
  8. data = json.load(f)
  9. print('%s查看票 目前剩余:%s' % (name, data.get('ticket_num')))
  10. def buy(name):
  11. # 先查询票数
  12. with open(r'data.json','r',encoding='utf8')as f:
  13. data = json.load(f)
  14. # 模拟网络延迟
  15. time.sleep(random.randint(1,3))
  16. # 买票
  17. if data.get('ticket_num') > 0:
  18. with open(r'data.json', 'w',encoding='utf8')as f:
  19. data['ticket_num'] -= 1
  20. json.dump(data,f)
  21. print('%s 买票成功' % name)
  22. else:
  23. print('%s 买票失败 非常可乐 没车回去了'% name)
  24. def run(name,mutex):
  25. search(name)
  26. mutex.acquire() # 抢锁
  27. buy(name)
  28. mutex.release() # 释放锁
  29. if __name__ == '__main__':
  30. mutex = Lock() # 产生一把锁
  31. for i in range(10):
  32. p = Process(target=run, args=('用户%s号' % i,mutex))
  33. p.start()
  34. """
  35. 锁有很多种 但是作用都一样
  36. 行锁 表锁。。。。
  37. """

线程理论

  1. 进程
  2. 进程其实是资源单位 表示一块内存空间
  3. 线程
  4. 线程才是执行单位 表示真正的代码指令
  5. 我们可以将进程比喻是车间 线程是车间里面的流水线
  6. 一个进程内部至少含有一个线程
  7. 1.一个进程内可以开设多个线程
  8. 2.同一个进程下的多个线程数据是共享的
  9. 3.创建进程与线程的区别
  10. 创建进程的消耗要远远大于线程

创建线程的两种方式

  1. from threading import Thread
  2. from multiprocessing import Process
  3. import time
  4. # def task(name):
  5. # print(f'{name}is running')
  6. # time.sleep(0.1)
  7. # print(f'{name}is over')
  8. #
  9. # if __name__ == '__main__':
  10. # start_time = time.time()
  11. # p_list = []
  12. # for i in range(100):
  13. # p = Process(target=task,args=('用户%s'%i,))
  14. # p.start()
  15. # p_list.append(p)
  16. # for p in p_list:
  17. # p.join()
  18. # print(time.time() - start_time)
  19. # t_list = []
  20. # for i in range(100):
  21. # p = Process(target=task, args=('用户%s' % i,))
  22. # p.start()
  23. # t_list.append(p)
  24. # for p in t_list:
  25. # p.join()
  26. # print(time.time() - start_time)
  27. #
  28. # t = Thread(target=task, args=('json',))
  29. # t.start()
  30. # print('主线程')
  31. """
  32. 创建线程无需考虑反复执行的问题
  33. """
  34. class MyThread(Thread):
  35. def run(self):
  36. print('run is running')
  37. time.sleep(1)
  38. print('run is over')
  39. obj = MyThread()
  40. obj.start()
  41. print('主线程')

线程的诸多特性

  1. 1.join方法
  2. 2.同进程内多个线程数据共享
  3. 3.current_thread()
  4. 4.active_count()

GIL全局解释器锁

  1. # 官方文档对GIL的解释
  2. In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPythons memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.
  3. """
  4. 1.在CPython解释器中存在全局解释器锁简称GIL
  5. python解释器有很多类型
  6. CPython JPython PyPython(常用的是CPython解释器)
  7. 2.GIL本质也是一把互斥锁 用来阻止同一个进程内多个线程同时执行(重要)
  8. 3.GIL的存在是因为CPython解释器中内存管理不是线程安全的(垃圾回收机制)
  9. 垃圾回收机制
  10. 引用计数 标记清除 分代回收
  11. """

验证GIL的存在

  1. from threading import Thread
  2. num = 100
  3. def task():
  4. global num
  5. num -= 1
  6. t_list = []
  7. for i in range(100):
  8. t = Thread(target=task)
  9. t.start()
  10. t_list.append(t)
  11. for t in t_list:
  12. t.join()
  13. print(num)

GIL与普通互斥锁

  1. 既然CPython解释器中有GIL 那么我们以后写代码是不是就不需要操作锁了!!!!
  2. """
  3. GIL只能够确保同进程内多线程数据不会被垃圾回收机制弄乱 并不能确保程序里面的数据是否安全
  4. """
  5. import time
  6. from threading import Thread,Lock
  7. num = 100
  8. def task(mutex):
  9. global num
  10. mutex.acquire()
  11. count = num
  12. time.sleep(0.1)
  13. num = count - 1
  14. mutex.release()
  15. mutex = Lock()
  16. t_list = []
  17. for i in range(100):
  18. t = Thread(target=task,args=(mutex,))
  19. t.start()
  20. t_list.append(t)
  21. for t in t_list:
  22. t.join()
  23. print(num)

python多线程是否有用

  1. 需要分情况
  2. 情况1
  3. 单个CPU
  4. 多个CPU
  5. 情况2
  6. IO密集型(代码有IO操作)
  7. 计算密集型(代码没有IO)
  8. 1.单个CPU
  9. IO 密集型
  10. 多进程
  11. 申请额外的空间 消耗更多的资源
  12. 多线程
  13. 消耗资源相对较少 通过多道技术
  14. ps:多线程有优势!!!
  15. 计算密集型
  16. 多进程
  17. 申请额外的空间 消耗更多的资源(总耗时+申请空间+拷贝代码+切换)
  18. 多线程
  19. 消耗资源相对较少 通过多道技术(总耗时+切换)
  20. ps:多线程有优势!!!
  21. 2.多个CPU
  22. IO密集型
  23. 多进程
  24. 总耗时(单个进程的耗时+IO+申请空间+拷贝代码)
  25. 多线程
  26. 总耗时(单个进程的耗时+IO)
  27. ps:多线程有优势!!!!
  28. 计算密集型
  29. 多进程
  30. 总耗时(单个进程的耗时)
  31. 多线程
  32. 总耗时(多个进程的综合)
  33. ps:多进程完胜!!!!!
  34. from threading import Thread
  35. from multiprocessing import Process
  36. import os
  37. import time
  38. def work():
  39. # 计算密集型
  40. res = 1
  41. for i in range(1, 100000):
  42. res *= i
  43. if __name__ == '__main__':
  44. # print(os.cpu_count()) # 12 查看当前计算机CPU个数
  45. start_time = time.time()
  46. # p_list = []
  47. # for i in range(12): # 一次性创建12个进程
  48. # p = Process(target=work)
  49. # p.start()
  50. # p_list.append(p)
  51. # for p in p_list: # 确保所有的进程全部运行完毕
  52. # p.join()
  53. t_list = []
  54. for i in range(12):
  55. t = Thread(target=work)
  56. t.start()
  57. t_list.append(t)
  58. for t in t_list:
  59. t.join()
  60. print('总耗时:%s' % (time.time() - start_time)) # 获取总的耗时
  61. """
  62. 计算密集型
  63. 多进程:5.665567398071289
  64. 多线程:30.233906745910645
  65. """
  66. def work():
  67. time.sleep(2) # 模拟纯IO操作
  68. if __name__ == '__main__':
  69. start_time = time.time()
  70. # t_list = []
  71. # for i in range(100):
  72. # t = Thread(target=work)
  73. # t.start()
  74. # for t in t_list:
  75. # t.join()
  76. p_list = []
  77. for i in range(100):
  78. p = Process(target=work)
  79. p.start()
  80. for p in p_list:
  81. p.join()
  82. print('总耗时:%s' % (time.time() - start_time))
  83. """
  84. IO密集型
  85. 多线程:0.0149583816528320
  86. 多进程:0.6402878761291504
  87. """

死锁现象

  1. from threading import Thread,Lock
  2. import time
  3. mutexA = Lock() # 产生一把锁
  4. mutexB = Lock() # 产生另一把锁
  5. class MyThread(Thread):
  6. def run(self):
  7. self.func1()
  8. self.func2()
  9. def func1(self):
  10. mutexA.acquire()
  11. print(f'{self.name}抢到了A锁')
  12. mutexB.acquire()
  13. print(f'{self.name}抢到了B锁')
  14. mutexB.release()
  15. print(f'{self.name}释放了B锁')
  16. mutexA.release()
  17. print(f'{self.name}释放了A锁')
  18. def func2(self):
  19. mutexB.acquire()
  20. print(f'{self.name}抢到了B锁')
  21. time.sleep(1) # 这个阻塞时间位置放到开始时不会出现
  22. mutexA.acquire()
  23. print(f'{self.name}抢到了A锁')
  24. mutexA.release()
  25. print(f'{self.name}释放了A锁')
  26. mutexB.release()
  27. print(f'{self.name}释放了B锁')
  28. for i in range(10):
  29. obj = MyThread()
  30. obj.start()
  31. """
  32. 死锁现象也是一个常见的现象 很典型 主要为了不要随便写锁 保证代码稳定没有问题再用
  33. """

信号量

  1. python中并发编程中信号量相当于多把互斥锁(公共厕所)
  2. from threading import Thread,Lock,Semaphore
  3. import time
  4. import random
  5. sp = Semaphore(5) # 一次性产生五把锁
  6. class MyThread(Thread):
  7. def run(self):
  8. sp.acquire()
  9. print(self.name)
  10. time.sleep(random.randint(1,3))
  11. sp.release()
  12. for i in range(20):
  13. t = MyThread()
  14. t.start()

event事件

  1. from threading import Thread, Event
  2. import time
  3. event = Event() # 类似于造了一个红绿灯
  4. def light():
  5. print('红灯亮着的 所有人都不能动')
  6. time.sleep(3)
  7. print('绿灯亮了 油门踩到底 冲冲冲!!!!!!')
  8. event.set()
  9. def car(name):
  10. print('%s 正在等红灯' % name)
  11. event.wait()
  12. print('%s加油门 飙车了' % name)
  13. t = Thread(target=light)
  14. t.start()
  15. for i in range(20):
  16. t = Thread(target=car, args=('熊猫PRO%s' % i,))
  17. t.start()

进程池与线程池

  1. 进程和线程能否无限制的创建 不可以
  2. 因为硬件的发展赶不上软件 有物理极限 如果我们在编写代码的过程中无限制的创建进程或者线程可能会导致计算机崩溃

  3. 降低程序的执行效率 但是保证了计算机硬件的安全
  4. 进程池
  5. 提前创建好固定数量的进程,供后续程序的调用 超出则等待
  6. 线程池
  7. 提前创建好固定数量的线程供后续程序的调用 超出则等待
  8. from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
  9. import os
  10. import time
  11. import random
  12. from threading import current_thread
  13. # 1.产生含有固定数量线程的线程池
  14. # pool = ThreadPoolExecutor(5)
  15. pool = ProcessPoolExecutor(5)
  16. def task(n):
  17. print('task is running')
  18. time.sleep(random.randint(1,3))
  19. print('tsk is over', n, current_thread().name)
  20. print('task is over', os.getpid())
  21. return '我是task函数的返回值'
  22. def func(*args, **kwargs):
  23. print('from func')
  24. if __name__ == '__main__':
  25. # 2.将认为提交给线程池即可
  26. for i in range(20):
  27. res = pool.submit(task,123) # 朝线程池提交任务
  28. print(res.result()) # 不能直接获取
  29. pool.submit(task,123).add_done_callback(func)

协程

  1. """
  2. 进程:资源单位
  3. 线程:执行单位
  4. 协程:单线程下实现并发(效率高)
  5. 在代码层面欺骗CPU 让CPU觉得代码里面没有IO操作
  6. 实际上IO操作被我们自己写的代码检测 一旦有 立刻让代码执行别的
  7. (该技术完全是程序员自己弄出来的 名字也是程序员自己起的)
  8. 核心:自己写代码完成切换+保存状态
  9. """
  10. import time
  11. from gevent import monkey; monkey.patch_all() # 固定编写 用于检测所有的IO操作(猴子补丁)
  12. from gevent import spawn # 第三方模块直接下载,这个模块还需要一个高版本的pycharm才可以下载使用
  13. def func1():
  14. print('func1 running')
  15. time.sleep(3)
  16. print('func1 over')
  17. def func2():
  18. print('func2 running')
  19. time.sleep(5)
  20. print('func2 over')
  21. if __name__ == '__main__':
  22. stat_time = time.time()
  23. func1()
  24. func2()
  25. s1 = spawn(func1) # 检测代码 一旦有IO自动切换(执行没有IO的操作 变向的等待IO结束)
  26. s2 = spawn(func2)
  27. s1.join()
  28. s2.join()
  29. print(time.time() - stat_time) # 8.0123434543 协程 5.015565753

协程实现并发

  1. import socket
  2. from gevent import monkey;monkey.patch_all() # 固定编写 用于检测所有的IO操作(猴子补丁)
  3. from gevent import spawn
  4. def communication(sock):
  5. while True:
  6. data = sock.recv(1024)
  7. print(data.decode('utf8'))
  8. sock.send(data.upper())
  9. def get_server():
  10. server = socket.socket()
  11. server.bind(('127.0.0.1', 8080))
  12. server.listen(5)
  13. while True:
  14. sock, addr = server.accept() # IO操作
  15. spawn(communication, sock)
  16. s1 = spawn(get_server)
  17. s1.join()
  18. 如何不断的提升程序的运行效率
  19. 多进程下开多线程 多线程下开协程

python之路32 网络并发线程方法 线程池 协程的更多相关文章

  1. Python菜鸟之路:Python基础-线程、进程、协程

    上节内容,简单的介绍了线程和进程,并且介绍了Python中的GIL机制.本节详细介绍线程.进程以及协程的概念及实现. 线程 基本使用 方法1: 创建一个threading.Thread对象,在它的初始 ...

  2. Python之路【第七篇】:线程、进程和协程

    Python之路[第七篇]:线程.进程和协程   Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 1 ...

  3. python并发编程之Queue线程、进程、协程通信(五)

    单线程.多线程之间.进程之间.协程之间很多时候需要协同完成工作,这个时候它们需要进行通讯.或者说为了解耦,普遍采用Queue,生产消费模式. 系列文章 python并发编程之threading线程(一 ...

  4. Python之路,Day9 - 线程、进程、协程和IO多路复用

    参考博客: 线程.进程.协程: http://www.cnblogs.com/wupeiqi/articles/5040827.html http://www.cnblogs.com/alex3714 ...

  5. Python之线程、进程和协程

    python之线程.进程和协程 目录: 引言 一.线程 1.1 普通的多线程 1.2 自定义线程类 1.3 线程锁 1.3.1 未使用锁 1.3.2 普通锁Lock和RLock 1.3.3 信号量(S ...

  6. Python开发【第九章】:线程、进程和协程

    一.线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 1.t ...

  7. py 并发编程(线程、进程、协程)

    一.操作系统 操作系统是一个用来协调.管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等.操作系统的内核的定义:操 ...

  8. Python 线程、进程和协程

    python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费时间,所以我们直接学习threading 就可以了. ...

  9. python运维开发(十一)----线程、进程、协程

    内容目录: 线程 基本使用 线程锁 自定义线程池 进程 基本使用 进程锁 进程数据共享 进程池 协程 线程 线程使用的两种方式,一种为我们直接调用thread模块上的方法,另一种我们自定义方式 方式一 ...

随机推荐

  1. linux操作系统运行一个java程序并外网访问

    (一)安装jdk 1.新建文档java  : mkdir java 2.进入java并且下载jdk     下载jdk : wget --no-check-certificate --no-cooki ...

  2. AgileBoot - 项目内统一的错误码设计

    本篇文章主要探讨关于统一错误码的设计,并提供笔者的实现 欢迎大家讨论,指正. 该错误码的设计在仓库: github:https://github.com/valarchie/AgileBoot-Bac ...

  3. hyperf-搭建初始化

    官方文档* https://hyperf.wiki/2.0/#/README 初步搭建1. 安装项目 composer create-project hyperf/hyperf-skeleton 2. ...

  4. CF Round #829 题解 (Div. 2)

    F 没看所以摆了 . 看拜月教教主 LHQ 在群里代打恰钱 /bx 目录 A. Technical Support (*800) B. Kevin and Permutation (*800) C. ...

  5. ssh登录提示hosts is down

    其他无用的网卡配置信息mv走重启network如果还是不行重启一下服务器问题就能解决

  6. fastjson反序列化漏洞历史CVE学习整理

    fastjson 1.2.24反序列化漏洞复现 先写一个正常的使用 fastjson的web服务 我们使用 springboot创建 主要是pom.xml 里面要添加fastjson fastjson ...

  7. C语言嵌套for循环实现冒泡排序

    使用嵌套for循环实现冒泡排序的一个函数. #include<stdio.h> /** * 介绍: * 使用嵌套for循环实现冒泡排序,由小到大(上小下大). * 参数: * sum[]: ...

  8. Go语言核心36讲31

    我们在前两篇文章中讨论了互斥锁.读写锁以及基于它们的条件变量,先来总结一下. 互斥锁是一个很有用的同步工具,它可以保证每一时刻进入临界区的goroutine只有一个.读写锁对共享资源的写操作和读操作则 ...

  9. npm安装hexo报错

    报错提示 npm WARN saveError ENOENT: no such file or directory, open '/home/linux1/package.json' npm noti ...

  10. 链接脚本(Linker Scripts)语法和规则解析(自官方手册)

    为了便于与英文原文对照学习与理解(部分翻译可能不准确),本文中的每个子章节标题和引用使用的都是官方手册英文原称.命令及命令行选项统一使用斜体书写.高频小节会用蓝色字体标出. 3 Linker Scri ...