ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

并发编程.多道技术,进程理论、如何创建进程

2022-01-13 19:35:26  阅读:147  来源: 互联网

标签:__ name Process 编程 print time 进程 多道


image

一、UDP代码编写(了解)

  • udp是无链接的,先启动哪一端都不会报错

import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM)  # UDP协议
udp_sk.bind(('127.0.0.1',9000))  # 绑定地址
msg,addr = udp_sk.recvfrom(1024)
udp_sk.sendto(b'hi',addr)             
udp_sk.close() 


import socket
ip_port=('127.0.0.1',9000)
udp_sk=socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b'hello',ip_port)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode('utf-8'),addr)

"""
时间服务器的实现原理
	1.内部小电容供电
	2.远程时间同步
"""

TCP协议与UDP协议的区别

  • UDP的recvfrom是阻塞的,一个recvfrom(x)必须对唯一一个sendinto(y),收完了x个字节的数据就算完成,若是y>x数据就丢失,这意味着udp根本不会粘包,但是会丢数据,不可靠
  • TCP的协议数据不会丢,没有收完包,下次接收,会继续上次继续接收,己端总是在收到ack时才会清除缓冲区内容。数据是可靠的,但是会粘包。

二、操作系统的发展史(了解)

"""学习并发编程其实就是在学习操作系统的发展史(底层逻辑)"""
1.穿孔卡片时代
	CPU的利用率极低
2.联机批处理系统
	将多个程序员的程序一次性录入磁带中 之后交由输入机输入并由CPU执行
3.脱机批处理系统
	现代计算机的雏形(远程输入 高速磁带 主机)

三、多道技术

  • 并发:是伪并行,多个任务看起来是同时运行。单个cpu+多道技术就可以实现并发,(并行也属于并发)

  • 并行:多个任务真正意义上的同时运行,只有具备多个cpu才能实现并行

  • 串行:一个任务运行完毕后才能开启下一个任务然后运行

# 前提:单核CPU
	多道技术
    	切换+保存状态
"""
CPU工作机制
	1.当某个程序进入IO状态的时候 操作系统会自动剥夺该程序的CPU执行权限
	2.当某个程序长时间占用CPU的时候 操作系统也会剥夺该程序的CPU执行权限
"""

并行与并发(******)
	并行:多个程序同时执行
    并发:多个程序只要看起来像同时运行即可
# 问:单核CPU能否实现并行
	肯定不能,但是可以实现并发
# 问:12306可以同一时间支持几个亿的用户买票 问是并行还是并发
	肯定是并发(高并发)		
星轨:微博能够支持八个星轨
  • 下面这个图可以看出单cpu运行轨迹

img

四、进程理论

  • 先来先服务调度算法FCFS:按作业或者进程到达的先后顺序依次调度;(平均周转时间可能会很长 )

  • 短作业优先调度算法SJF:算法从就绪队列中选择估计时间最短的作业进行处理,直到得出结果或者无法继续执行(周转时间短,但是响应时间长 )

  • 高相应比算法HRN:响应比=(等待时间+要求服务时间)/要求服务时间;

  • 时间片轮转调度RR:按到达的先后对进程放入队列中,然后给队首进程分配CPU时间片,时间片用完之后计时器发出中断,暂停当前进程并将其放到队列尾部,循环 ;(响应时间可以得到保证)

  • 多级反馈队列调度算法:目前公认较好的调度算法;设置多个就绪队列并为每个队列设置不同的优先级,第一个队列优先级最高,其余依次递减。优先级越高的队列分配的时间片越短,进程到达之后按FCFS放入第一个队列,如果调度执行后没有完成,那么放到第二个队列尾部等待调度,如果第二次调度仍然没有完成,放入第三队列尾部…。只有当前一个队列为空的时候才会去调度下一个队列的进程。

img

# 进程与程序的区别
	程序:一堆代码(死的)
    进程:正在运行的程序(活的)
    
# 单核情况下的进程调度
	进程调度算法演变
    	1.FCFS	先来先服务
        	对短作业不友好
        2.短作业优先调度算法
        	对长作业不友好
        3.时间片轮转法+多级反馈队列
        	先分配给新的多个进程相同的时间片
            之后根据进程消耗的时间片多少分类别......
 
# 进程三状态图(******)
	就绪态 运行态 阻塞态
    	进程要想进入运行态必须先经过就绪态
      
# 同步与异步(******)
	'''用于描述任务的提交方式'''
	同步:提交完任务之后原地等待任务的返回结果 期间不做任何事
    异步:提交完任务之后不原地等待任务的返回结果 直接去做其他事 结果由反馈机制自动提醒
      
# 阻塞与非阻塞(******)
	'''用于描述任务的执行状态'''
    阻塞:阻塞态
    非阻塞:就绪态 运行态

五、创建进程

注意:在windows中Process()必须放到# if *name* == '*main*':下

开启进程的方式一:可以让多个任务并发起来在后台同时运行

# 代码层面创建进程

from multiprocessing import Process
import time
import os


def test(name):
    print(os.getpid())  # 获取进程号
    print(os.getppid())  # 获取父进程号
    print('%s正在运行' % name)
    time.sleep(3)
    print('%s已经结束' % name)


if __name__ == '__main__':
    p = Process(target=test, args=('jason',))  # 生成一个进程对象
    p.start()  # 告诉操作系统开设一个新的进程     异步提交
    print(os.getpid())
    print('主')


"""
在windows中开设进程类似于导入模块
    从上往下再次执行代码
一定需要在__main__判断语句内执行开设进程的代码

在linux中是直接将代码完整的复制一份执行
    不需要在__main__判断语句内执行
"""


class MyProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print('%s正在运行' % self.name)
        time.sleep(3)
        print('%s已经结束' % self.name)

if __name__ == '__main__':
    p = MyProcess('jason')
    p.start()
    print('主')

image

六、进程的join方法

  • 加上join并不是变成串行了,而是看join放在什么位置,join往后放看到的是并发

from multiprocessing import Process
import time


def test(name, n):
    print('%s is running' % name)
    time.sleep(n)
    print('%s is over' % name)


if __name__ == '__main__':
    p_list = []
    start_time = time.time()
    for i in range(1, 4):
        p = Process(target=test, args=(i, i))
        p.start()
        p_list.append(p)
        # p.join()  # 串行  9s+
    for p in p_list:
        p.join()
    print(time.time() - start_time)

    # p = Process(target=test, args=('jason',))
    # p1 = Process(target=test, args=('kevin',))
    # p2 = Process(target=test, args=('oscar',))
    # p.start()
    # p1.start()
    # p2.start()
    print('主进程')

七、进程间默认无法交互

# 进程间数据是相互隔离的
from multiprocessing import Process

money = 100


def test():
    global money
    money = 999


if __name__ == '__main__':
    p = Process(target=test)
    p.start()
    # 先确保子进程运行完毕了 再打印
    p.join()
    print(money)

八、对象方法

"""
1.current_process查看进程号
2.os.getpid() 查看进程号  os.getppid() 查看父进程进程号
3.进程的名字,p.name直接默认就有,也可以在实例化进程对象的时候通过关键字形式传入name=''
3.p.terminate()  杀死子进程 
4.p.is_alive()  判断进程是否存活	3,4结合看不出结果,因为操作系统需要反应时间。主进程
睡0.1即可看出效果
"""

ps:进程对象代码实现方法

# 例1:
from multiprocessing import Process
import os
import time

count = 100

def task():
    global count
    count = 0

if __name__ == '__main__':
    p = Process(target=task)
    p.start()  # 通知操作系统开启进程
    p.join()   # 主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)
    print("主",count)

    
    
# 例2:

from multiprocessing import Process
import os
import time

def task(n):
    print(os.getpid())
    time.sleep(n)

if __name__ == '__main__':
    p1 = Process(target=task,args=(3,))
    p2 = Process(target=task,args=(2,))
    p3 = Process(target=task,args=(1,))

    start = time.time()
    p1.start()  # 通知操作系统开启进程
    p1.join()

    p2.start()  # 通知操作系统开启进程
    p2.join()

    p3.start()  # 通知操作系统开启进程
    p3.join()

    stop = time.time()
    print(stop - start)
# 加上join并不是变成串行了,而是看join放在什么位置,join往后放看到的是并发

# 例3:

from multiprocessing import Process
import os
import time


def task(n):
    print(os.getpid())
    time.sleep(n)


if __name__ == '__main__':
    p1 = Process(target=task, args=(3,),name='进程1')
    p1.start()
    print(p1.name,p1.pid)
    # p1.join()
    p1.terminate()
    time.sleep(0.01)
    print(p1.is_alive())

image

标签:__,name,Process,编程,print,time,进程,多道
来源: https://www.cnblogs.com/gengjian/p/15799352.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有