多进程实现TCP服务端并发

import socket
from multiprocessing import Process def get_server():
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
return server def get_talk(sock):
while True:
data = sock.recv(1024)
print(data.decode('utf8'))
sock.send(data.upper()) if __name__ == '__main__':
server = get_server()
while True:
sock, addr = server.accept()
# 开设多进程去聊天
p = Process(target=get_talk, args=(sock,))
p.start()

互斥锁代码实操

锁:建议只加载操作数据的部分 否则整个程序的效率会极低
from multiprocessing import Process, Lock
import time
import json
import random def search(name):
with open(r'data.json', 'r', encoding='utf8') as f:
data = json.load(f)
print('%s查看票 目前剩余:%s' % (name, data.get('ticket_num'))) def buy(name):
# 先查询票数
with open(r'data.json', 'r', encoding='utf8') as f:
data = json.load(f)
# 模拟网络延迟
time.sleep(random.randint(1, 3))
# 买票
if data.get('ticket_num') > 0:
with open(r'data.json', 'w', encoding='utf8') as f:
data['ticket_num'] -= 1
json.dump(data, f)
print('%s 买票成功' % name)
else:
print('%s 买票失败 非常可怜 没车回去了!!!' % name) def run(name, mutex):
search(name)
mutex.acquire() # 抢锁
buy(name)
mutex.release() # 释放锁 if __name__ == '__main__':
mutex = Lock() # 产生一把锁
for i in range(10):
p = Process(target=run, args=('用户%s号' % i, mutex))
p.start()
"""
锁有很多种 但是作用都一样
行锁 表锁 ...
"""

线程理论

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

创建线程的两种方式

from threading import Thread

import time

def task(name):
print(f'{name} is running')
time.sleep(0.1)
print(f'{name} is over') t = Thread(target=task, args=('jason',))
t.start()
print('主线程')
# 第二种方式
class MyThread(Thread):
def run(self):
print('run is running')
time.sleep(1)
print('run is over') obj = MyThread()
obj.start()
print('主线程')

线程的诸多特性

# 线程join方法
from threading import Thread
import time def task(name):
print(f'{name} is running')
time.sleep(3)
print(f'{name} is over') t = Thread(target=task, args=('jason',))
t.start()
t.join() # 主线程代码等待子线程代码运行完毕之后再往下执行
print('主线程')
"""
主线程为什么要等着子线程结束才会结束整个进程
因为主线程结束也就标志着整个进程的结束 要确保子线程运行过程中所需的各项资源
"""
# 同进程内多个线程数据共享
from threading import Thread money = 100
def task():
global money
money = 1 t = Thread(target=task)
t.start()
t.join()
print(money)
# 思考:线程更改进程内数据,数据也会被更改
# 1
线程对象属性和方法
1、同一进程下多个线程的进程号一致
2、如何统计进程下活跃的线程数
active_count()
3、获取线程的名字
1.current_thread().name
MainThread # 主线程
Thread-1、Thread-2 # 子线程
2.self.name # 类对象获取线程名

GIL全局解释器锁

# 官方文档对GIL的解释
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 CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.
"""
1.在CPython解释器中存在全局解释器锁简称GIL
python解释器有很多类型
CPython JPython PyPython (常用的是CPython解释器)
2.GIL本质也是一把互斥锁 用来阻止同一个进程内多个线程同时执行(重要)
3.GIL的存在是因为CPython解释器中内存管理不是线程安全的(垃圾回收机制)
垃圾回收机制
引用计数、标记清除、分代回收
"""

验证GIL的存在

from threading import Thread

num = 100

def task():
global num
num -= 1 t_list = []
for i in range(100):
t = Thread(target=task)
t.start()
t_list.append(t)
for t in t_list:
t.join()
print(num)

GIL与普通互斥锁

既然CPython解释器中有GIL 那么我们以后写代码是不是就不需要操作锁了!!!
"""
GIL只能够确保同进程内多线程数据不会被垃圾回收机制弄乱
并不能确保程序里面的数据是否安全
"""
import time
from threading import Thread,Lock num = 100 def task(mutex):
global num
mutex.acquire()
count = num
time.sleep(0.1)
num = count - 1
mutex.release() mutex = Lock()
t_list = []
for i in range(100):
t = Thread(target=task,args=(mutex,))
t.start()
t_list.append(t)
for t in t_list:
t.join()
print(num)
注意:如果这里没加互斥锁mutex的时候,结果为99,为什么?
分析:因为如果没有互斥锁保证它独立运行完再运行下一个的话,每个线程获取到的money都是100,tmp-1都是99,那么最终结果也就是99 """
GIL是一个纯理论知识 在实际工作中根本无需考虑它的存在 GIL作用面很窄 仅限于解释器级别
后期我们要想保证数据的安全应该自定义互斥锁(使用别人封装好的工具)
"""

python多线程是否有用

需要分情况
情况1
单个CPU
多个CPU
情况2
IO密集型(代码有IO操作)
计算密集型(代码没有IO) 1.单个CPU
IO密集型
多进程
申请额外的空间 消耗更多的资源
多线程
消耗资源相对较少 通过多道技术
ps:多线程有优势!!!
计算密集型
多进程
申请额外的空间 消耗更多的资源(总耗时+申请空间+拷贝代码+切换)
多线程
消耗资源相对较少 通过多道技术(总耗时+切换)
ps:多线程有优势!!!
2.多个CPU
IO密集型
多进程
总耗时(单个进程的耗时+IO+申请空间+拷贝代码)
多线程
总耗时(单个进程的耗时+IO)
ps:多线程有优势!!!
计算密集型
多进程
总耗时(单个进程的耗时)
多线程
总耗时(多个进程的综合)
ps:多进程完胜!!!
from threading import Thread
from multiprocessing import Process
import os
import time def work():
# 计算密集型
res = 1
for i in range(1, 100000):
res *= i if __name__ == '__main__':
# print(os.cpu_count()) # 12 查看当前计算机CPU个数
start_time = time.time()
# p_list = []
# for i in range(12): # 一次性创建12个进程
# p = Process(target=work)
# p.start()
# p_list.append(p)
# for p in p_list: # 确保所有的进程全部运行完毕
# p.join()
t_list = []
for i in range(12):
t = Thread(target=work)
t.start()
t_list.append(t)
for t in t_list:
t.join()
print('总耗时:%s' % (time.time() - start_time)) # 获取总的耗时 """
计算密集型
多进程:5.665567398071289
多线程:30.233906745910645
"""
def work():
time.sleep(2) # 模拟纯IO操作 if __name__ == '__main__':
start_time = time.time()
# t_list = []
# for i in range(100):
# t = Thread(target=work)
# t.start()
# for t in t_list:
# t.join()
p_list = []
for i in range(100):
p = Process(target=work)
p.start()
for p in p_list:
p.join()
print('总耗时:%s' % (time.time() - start_time)) """
IO密集型
多线程:0.0149583816528320
多进程:0.6402878761291504
"""

死锁现象

from threading import Thread, Lock
import time mutexA = Lock()
mutexB = Lock() class MyThread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
mutexA.acquire() # 抢A锁
print(f'{self.name}抢到了A锁')
mutexB.acquire() # 抢B锁
print(f'{self.name}抢到了B锁')
mutexB.release() # 放B锁
mutexA.release() # 放A锁
def f2(self):
mutexB.acquire() # 抢B锁
print(f'{self.name}抢到了B锁')
time.sleep(2)
mutexA.acquire() # 抢A锁
print(f'{self.name}抢到了A锁')
mutexA.release() # 放A锁
mutexB.release() # 放B锁
for i in range(10): # 创建10个线程
t = MyThread()
t.start()
# 结果:
Thread-1抢到了A锁
Thread-1抢到了B锁
Thread-1抢到了B锁
Thread-2抢到了A锁
# 然后就产生阻塞现象了,因为最后线程2抢到A锁然后取抢B锁时,B锁还在线程1手里,然而线程1下面也要抢A锁,两者都进入阻塞
结论:
锁不能轻易使用并且以后我们也不会在自己去处理锁都是用别人封装的工具
ps:锁就算掌握了如何抢 如何放 也会产生死锁现象

网络编程:多进程实现TCP服务端并发、互斥锁代码实操、线程理论、创建线程的两种方式、线程的诸多特性、GIL全局解释器锁、验证GIL的存在的更多相关文章

  1. python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程

    GIL全局解释器锁 ''' python解释器: - Cpython C语言 - Jpython java ... 1.GIL: 全局解释器锁 - 翻译: 在同一个进程下开启的多线程,同一时刻只能有一 ...

  2. 进程池与线程池、协程、协程实现TCP服务端并发、IO模型

    进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度 ...

  3. TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q

    TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...

  4. 网络版shell之网络编程练习篇--telnet服务端

    网络版shell之网络编程练习篇--telnet服务端   以前写过一个shell命令解释器,对与shell命令解释器的执行流程有了清晰的认识,这段时间学习网络编程,至于网络编程的细节以及知识点,已经 ...

  5. 8.14 day32 TCP服务端并发 GIL解释器锁 python多线程是否有用 死锁与递归锁 信号量event事件线程q

    TCP服务端支持并发 解决方式:开多线程 服务端 基础版 import socket """ 服务端 1.要有固定的IP和PORT 2.24小时不间断提供服务 3.能够支 ...

  6. python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03

    目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...

  7. 网络编程之多线程——GIL全局解释器锁

    网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...

  8. Python并发编程-GIL全局解释器锁

    Python并发编程-GIL全局解释器锁 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.GIL全局解释器锁概述 CPython 在解释器进程级别有一把锁,叫做GIL,即全局解释 ...

  9. 10 并发编程-(线程)-GIL全局解释器锁&死锁与递归锁

    一.GIL全局解释器锁 1.引子 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Pyt ...

  10. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

随机推荐

  1. 【pkuwc2018】随机算法

    我们考虑用状压dp来解决这一道题 设$f[i][S]$表示当前排列的前i位所构成的最大独立集恰好为S的方案数 我们考虑用$f[i][S]$推出$f[i+1][S']$的值 那么我们有两种扩展的方法,一 ...

  2. 最强cron解析器

    背景 大家有没有这么一种困境 我现在需要去配置一个定时任务:"每天早上九点执行任务" 若你有一个好的定时任务平台,相信很容易就能配置完成.那若是没有定时任务平台呢?是不是就要自己写 ...

  3. 第六章:Django 综合篇 - 11:分页 Paginator

    分页功能是几乎所有的网站上都需要提供的功能,当你要展示的条目比较多时,必须进行分页,不但能减小数据库读取数据压力,也有利于用户浏览. Django又很贴心的为我们提供了一个Paginator分页工具, ...

  4. 13. 第十二篇 二进制安装kubelet

    文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247483842&idx=1&sn=1ef1cb06 ...

  5. KVM里安装不是原装的winxp系统镜像

    从网上下载的winxp系统镜像,虽然是iso格式的,但是里面的内容是如下情况的 因此安装的话,需要采取如下步骤 1.添加一个光驱引导,挂载一个iso格式的pe 2.再添加一个光驱,挂载iso格式的wi ...

  6. EFK-4::ElasticSearch集群TLS加密通讯

    转载自:https://mp.weixin.qq.com/s?__biz=MzUyNzk0NTI4MQ==&mid=2247483822&idx=1&sn=6813b22eb5 ...

  7. k8s使用心得

    查看当前所有namespaces [root@master ~]# kubectl get namespaces -A NAME STATUS AGE default Active 63d hkd A ...

  8. .Net下的分布式唯一ID

    分布式唯一ID,顾名思义,是指在全世界任何一台计算机上都不会重复的唯一Id. 在单机/单服务器/单数据库的小型应用中,不需要用到这类东西.但在高并发.海量数据.大型分布式应用中,这类却是构建整个系统的 ...

  9. SpringBoot的starter到底是什么?

    前言 我们都知道,Spring的功能非常强大,但也有些弊端.比如:我们需要手动去配置大量的参数,没有默认值,需要我们管理大量的jar包和它们的依赖. 为了提升Spring项目的开发效率,简化一些配置, ...

  10. PHP全栈开发(四): HTML 学习(3. form 表单)

    form 表单标签 它表的是一个区域,而非是一个具体的某个元素,它也是作为一个容器的存在. 表单域主要是允许用户在表单域中输入内容,比如文本框,下拉列表,单选框,复选框,等等. <!DOCTYP ...