0
点赞
收藏
分享

微信扫一扫

并发编程(进程篇,未完待续)


文章目录

  • ​​一、socketserver模块​​
  • ​​1.服务端​​
  • ​​2.客户端1​​
  • ​​3.客户端2​​
  • ​​4.效果截图​​
  • ​​二、一些重要知识​​
  • ​​三、创建进程的两种方式和join方法​​
  • ​​1.非程序方面开启进程​​
  • ​​2.程序层面开启进程​​
  • ​​3.join方法​​
  • ​​四、进程间数据隔离​​
  • ​​五、进程对象及其他方法​​
  • ​​六、僵尸进程、孤儿进程、守护进程​​
  • ​​七、互斥锁​​
  • ​​八、队列&消息队列、IPC机制​​
  • ​​九、生产者消费者模型​​

一、socketserver模块

  • 该模块用于在网络编程中实现并发效果
  • 下面模拟一个客户输入信息然后服务端返回信息大写的并发效果

1.服务端

import socketserver

#基于tcp协议
'''
self.request=>conn
'''
class MyRequestHandle(socketserver.BaseRequestHandler):
def handle(self):
print(self.client_address)
while True:
try:
msg = self.requset.recv(1024)
if len(msg) == 0: break
self.request.send(msg.upper())
except Exception:
break
self.request.close()

#服务端应该做两件事情
#第一件事:循环地从半链接池中取出链接 请求与其建立双向链接
#第二件事:拿到链接对象,与其进行通信循环

s=socketserver.TCPServer(('127.0.0.1',8880),MyRequestHandle)
s.serve_forever()

2.客户端1

import socket


client = socket(AF_INET,SOCK_STREAM)
cliene.connect(('127.0.0.1',8880))

while True:
msg = input('请输入命令:').strip()
if len(msg) == 0: continue
client.send(msg.encode('utf-8'))

res = client.rece(1024)
print(res.decode('utf-8'))

3.客户端2

import socket


client = socket(AF_INET,SOCK_STREAM)
cliene.connect(('127.0.0.1',8880))

while True:
msg = input('请输入命令:').strip()
if len(msg) == 0: continue
client.send(msg.encode('utf-8'))

res = client.rece(1024)
print(res.decode('utf-8'))

4.效果截图

并发编程(进程篇,未完待续)_队列


并发编程(进程篇,未完待续)_复用_02


并发编程(进程篇,未完待续)_复用_03

二、一些重要知识

  • 操作系统的发展历史是围绕提高CPU运行效率展开的
  • 进程:正在运行的程序
  • 程序:代码
  • 多道技术:
  • 目的:单核实现并发
  • 主要是实现程序对计算机的空间复用和时间复用
  • 空间复用:多个程序共用一计算机硬件系统
  • 时间复用:保存程序的运行状态+切换程序
    +切换分为两种情况:
    1.程序遇到IO操作
    2.程序运行时间过长
  • 并行和并发
  • 并发:看起来像同时在做不同事情
  • 并行:同时做不同的事情
  • 进程的调度
  • 先来先服务调度算法
  • 短作业优先调度算法
  • 时间片轮转法+多级反馈队列
  • 进程三状态
    +就绪态、运行态、阻塞态
    +程序要进入运行态前必然经历就绪态
    +阻塞态就是遇到IO等操作会进入阻塞态
  • 同步&异步、阻塞&非阻塞
  • 同步异步是针对任务提交而言
  • 阻塞非阻塞是针对程序运行状态而言
  • 效率最高的就是异步非阻塞

三、创建进程的两种方式和join方法

1.非程序方面开启进程

随便双击几个应用,几个应用同时运行就是开了多个进程

2.程序层面开启进程

​​创建进程的两种方式​​ 第一种应用颇多

3.join方法

  • 简单来说就是让主进程等着子进程运行完之后,主程序再往下运行
  • 我们来做一个程序时间测试的小程序

from multiprocessing import Process
import time

def task(i):
time.sleep(i)

if __name__ == '__main__':
pro_lis = []
start = time.time()
# 创建三个进程
for i in range(3):
p = Process(target=task,args=(i,))
pro_lis.append(p)

# 启动三个进程
for pro in pro_lis:
pro.start()
print(time.time()-start)

运行结果:0.0258924961090087

尽管这并不是程序最终运行时间,实际上时间应该是2s多,但结合下面例子你足以看出join的用法,有点并发变串行的感觉。

from multiprocessing import Process
import time

def task(i):
time.sleep(i)

if __name__ == '__main__':
pro_lis = []
start = time.time()
# 创建三个进程
for i in range(3):
p = Process(target=task,args=(i,))
pro_lis.append(p)

# 启动三个进程
for pro in pro_lis:
pro.start()
pro.join()
print(time.time()-start)

结果:4.735849142074585

四、进程间数据隔离

  • 这是一个结论,我们来验证一下

from multiprocessing import Process


money = 100


def task():
global money # 局部修改全局
money = 666
print('子',money)


if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(money)

Result:

子 666
100

五、进程对象及其他方法

  • p.terminate() # 杀死当前进程
  • p.is_alive() # 判断当前进程是否存活
  • os.getpid() 获得进程号 等同于current_process().pid
  • 补充:Windows:cmd里 tasklist查看所有进程
  • tasklist | find “关键字” 可以对结果进行过滤,即单独获取某个程序的进程
    +os.getppid() #获得父进程号

from multiprocessing import Process, current_process
import time
import os


def task():
print('%s is running'%current_process().pid) # 查看当前进程的进程号
print('%s is running'%os.getpid()) # 查看当前进程的进程号
print('子进程的主进程号%s'%os.getppid()) # 查看当前进程的进程号
time.sleep(30)


if __name__ == '__main__':
p = Process(target=task)
p.start()
p.terminate() # 杀死当前进程
# 是告诉操作系统帮你去杀死当前进程 但是需要一定的时间 而代码的运行速度极快
time.sleep(0.1)
print(p.is_alive()) # 判断当前进程是否存活
"""
一般情况下我们会默认将
存储布尔值的变量名
和返回的结果是布尔值的方法名
都起成以is_开头
"""
print('主')
print('主',current_process().pid)
print('主',os.getpid())
print('主主',os.getppid()) # 获取父进程的pid号

结果:

False

主 9256
主 9256
主主 18360

六、僵尸进程、孤儿进程、守护进程

  • 僵尸进程指的是该进程结束后没死完,会保留一段时间,供父进程查看这个进程的进程号、运行时间等信息,当父进程存在一直在产生子进程的时候,无限开辟内存空间,这是不好的
  • 孤儿进程是子进程存活,而父进程死亡,操作系统有个机制会解决孤儿进程回收问题
  • 守护线程是跟着操作系统同生共死的进程
  • p.daemon = True # 将进程p设置成守护进程
  • 这一句一定要放在start方法上面才有效否则会直接报错

一个例子:古代皇帝驾崩其身边太监也必须gameover

from multiprocessing import Process
import time


def task(name):
print('%s总管正在活着'% name)
time.sleep(3)
print('%s总管正在死亡' % name)


if __name__ == '__main__':
p = Process(target=task,args=('太监',))
# p = Process(target=task,kwargs={'name':'egon'})
p.daemon = True # 将进程p设置成守护进程 这一句一定要放在start方法上面才有效否则会直接报错
p.start()
print('皇帝寿终正寝')

结果:注意太监。。

皇帝寿终正寝

注释守护进程之后

from multiprocessing import Process
import time


def task(name):
print('%s总管正在活着'% name)
time.sleep(3)
print('%s总管正在死亡' % name)


if __name__ == '__main__':
p = Process(target=task,args=('太监',))
# p = Process(target=task,kwargs={'name':'egon'})
# p.daemon = True # 将进程p设置成守护进程 这一句一定要放在start方法上面才有效否则会直接报错
p.start()
print('皇帝寿终正寝')

结果:

皇帝寿终正寝
太监总管正在活着
太监总管正在死亡

七、互斥锁

八、队列&消息队列、IPC机制

九、生产者消费者模型


举报

相关推荐

0 条评论