day34

今日所学:


"""
tcp 粘包问题
udp 的使用场景
udp适用于,对速度要求高,但是对数据完整性要求不高,不要求顺序,不需要链接
udp与tcp的区别:
udp 优点:不粘包,效率高适合数据量小的传输,不要求顺序,
缺点:不可靠传输,数据越大,丢包的风险越大
tcp 优点:可靠传输,对数据可靠要求性要求较高的,保证数据的完整性
缺点:比udp传输速度慢,容易粘包
网络编程:目前的 无法并发处理多个客户端
进程:来自于操作系统而言,在第三代操作系统中产生,诞生了多道技术
多到技术,是为了提高计算机资源的利用率,第三代以前是串行执行批处理数据
空间复用性:
同一时间在内存中存储多个程序数据
内存区域要相互隔离,物理隔离,你是不可能随意访问的
时间复用
切换+保护
当一个进程遇到了io 操作时,就切换其他进程来执行,切换前要进行当前运行状态
遇到io
运行时间过长,时间片用完了
"""
# from multiprocessing import Process
# import time

#
# def task():
# print("入宫了")
# time.sleep(50)
# print("结束了")
#
#
# if __name__ == '__main__':
# print("登记了")
#
# p = Process(target=task)
# # 设置为守护进程 必须在开启前就设置好
# p.daemon = True
# p.start()
#
# time.sleep(3)
# print("故事结束了")
# import random, time
# from multiprocessing import Process, Lock
#
#
# def task1(lock):
# lock.acquire()
# print("杨幂看见了老鼠")
# print(" 蔡徐坤好冤枉")
# lock.release()
#
#
# def task2(lock):
# # 要开始使用 上锁 需要导入一个类Lock
# lock.acquire() # 上锁
# print("奥,my,god")
# time.sleep(random.randint(0, 2))
# print("蔡徐坤打篮球")
# time.sleep(random.randint(0, 2))
# print("到达人生高潮!")
# # 用完了就解锁
# lock.release() # 把中间代码锁起来了
#
#
# def task3(lock):
# lock.acquire()
# print("蔡徐坤哭了")
# print("裤裆扯了")
# lock.release()
#
#
# def task4(lock):
# lock.acquire() # 上锁
# print("杨幂也在打篮球")
# time.sleep(random.randint(0, 2))
# print("杨幂报警了")
# time.sleep(random.randint(0, 2))
# print("蔡徐坤又哭了")
# lock.release() # 释放,解锁
#
#
# if __name__ == '__main__':
# lock = Lock() # 实例化Lock这个类 就是子进程一次性都可以用
# p1 = Process(target=task1, args=(lock,))
# p2 = Process(target=task2, args=(lock,))
# p3 = Process(target=task3, args=(lock,))
# p4 = Process(target=task4, args=(lock,)) # 给他的参数为元组
#
# p1.start()
# p2.start()
# p3.start()
# p4.start()
"""并发将带来资源的竞争问题
当多个进程同时操作同一个资源时,将会导致数据错乱的问题
解决方案:如join
弊端,1, 把原本并发的任务变成了串行,避免了数据的错乱问题,但是效率降低了,这样就没必要开子进程了
2,原本多个进程之间是公平竞争,join执行的顺序定死了,这是不合理的
解决方案:
就是给公共资源加锁,互斥锁
互斥锁:互相排斥的锁,如果资源被锁了,其他进程就无法使用了
锁并不是真的真的把资源锁起来只是在代码层面限制你的代码不能执行
锁和join的区别:
join是固定了执行顺序,会造成父进程等待子进程
锁依然是公平竞争,谁先抢到谁就先执行,父进程可以做其他进程
join是把要执行的进程的任务全部串行执行
而lock锁,可以锁定任意进程进行执行,就是一行代码也可以
注意注意: 互斥锁使用不要对同一把执行多次acquire ,会锁死导致程序无法执行
一次acquire必须对应一次release
什么时候加锁:多个进程要操作同一个资源的时候,这个资源可以是内存数据,也可以是文件数据等
想要数据安全,必须保证所有进程使用同一把锁
称之为:粒度 粒度越大意味着锁住的代码越多 效率越低
粒度越小意味着锁住的代码越少 效率越高
MYSQL 中不同隔离级别 其实就是不同的粒度
"""
""""
过程:
1.查询余票
2,购买
1,再次查询余票
2,有余票则购买成功 没有则失败

"""
# 查询.
# import json, os,time,random
# from multiprocessing import Process,Lock
#
#
# def show_ticket():
# with open("111.json", "rt", encoding="utf-8")as f:
# data = json.load(f)
# time.sleep(random.randint(0,2))
# print("%s剩余票数%s" % (os.getpid(), data["count"]))
#
#
# def buy_ticket():
# with open("111.json", "rt", encoding="utf-8")as f:
# data = json.load(f)
# if data["count"] > 0:
# data["count"] -= 1
# with open("111.json", "wt", encoding="utf-8") as f:
# json.dump(data, f)
# print("%s恭喜你抢票成功!" % os.getpid())
# else:
print("%s抢票失败,被人抢走了!" % os.getpid())


def task(lock):
show_ticket()
lock.acquire()
# show_ticket()
buy_ticket()
lock.release()

if __name__ == '__main__':
lock = Lock()
# 三个人买票
for i in range(10):
p = Process(target=task,args=(lock,))
p.start()

"""IPC 进程间通讯
通讯就是交换数据
进程之间内存是相互隔离的,当一个进程想要把数据给另一个进程,就需要考虑IPC
方式:
管道,只能单向通讯,数据都是二进制,
文件,在硬盘上创建共享文件
缺点速度慢,
优点 ,数据几乎没有限制
socket 编程复杂度较高
解决方法:共享内存,必须由操作系统来分配********
优点:速度快
缺点是,数据量不能太大


"""
from multiprocessing import Process
from multiprocessing import Manager, Lock
import time


# def task(data):
def task(data, l):
# data["num"] -= 1
l.acquire()
num = data["num"] # 10
time.sleep(0.1)
data["num"] = num - 1
l.release()


if __name__ == '__main__':

# 这儿的data和子进程没有关系,内存相互隔离,无论何时都是他自身的
# 这时候如果要共享内存 Manager 开启一个共享的字典
m = Manager() #
data = m.dict({"num": 10}) # 此时就完成了共享这个步骤
l = Lock()
for i in range(10):
p = Process(target=task, args=(data, l)) # 不要在这里忘了加 l这个参数
p.start()
time.sleep(2)
print(data)
"""
共享内存的方式:
1, Manager类 它提供很多数据结构,例如list, dict等等
它所创建出来的数据结构具备进程间共享的特点
2,Queue 队列 帮我们处理了锁的问题
队列是一种特殊的数据结构,先存储的先取出
相反的是先存储的后取出
函数的嵌套调用,就是这种类型。先调的后执行,即先进后出
函数的调用栈:堆栈存储,进出,栈是容器
调用函数时 函数入栈,函数结束就是出栈


"""
from multiprocessing import Queue


# 创建队列,不指定maxsize 则没有数量限制
#存储元素
q = Queue(3) #可以理解为一个容器
q.put("112")
q.put("abc")
q.put("kkk")

# 取出元素 只要取出元素,那么这个元素就不存在在原来的容器中,即直接取走
print(p.get())
print(p.get())
print(p.get())
# 如果取完容器中的元素,你还在取,那么他就卡住了,等别人操作完你在往里面塞
# 如果容量已经满了,在调用put时将进入阻塞状态,直到有人从队列中拿走一个数据,有了空位置,才会继续执行
# 如果队列已经空了,在调用get时将进入阻塞状态,直到有人存储了数据到队列后,才能继续执行


原文地址:https://www.cnblogs.com/Fzhiyuan/p/10970674.html