并发编程总结一,进程

并发编程总结: 一:操作系统 二:进程 三:线程 四:协程 ps; 注意知识

 一:操作系统   总结:   程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,  这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱了出来,  只需要考虑自己的应用软件的编写就可以了,应用软件直接使用操作系统提供的功能来间接使用硬件。   精简的说的话,操作系统就是一个协调、管理和控制计算机硬件资源和软件资源的控制程序

  细说的话,操作系统应该分成两部分功能   一:隐藏了丑陋的硬件调用接口,为应用程序员提供调用硬件资源的更好,更简单,更清晰的模型(系统调用接口)。    应用程序员有了这些接口后,就不用再考虑操作硬件的细节,专心开发自己的应用程序即可。    例如:操作系统提供了文件这个抽象概念,对文件的操作就是对磁盘的操作,     有了文件我们无需再去考虑关于磁盘的读写控制(比如控制磁盘转动,移动磁头读写数据等细节),   二:将应用程序对硬件资源的竞态请求变得有序化    例如:很多应用软件其实是共享一套计算机硬件,比方说有可能有三个应用程序同时需要申请打印机来输出内容,     那么a程序竞争到了打印机资源就打印,然后可能是b竞争到打印机资源,     也可能是c,这就导致了无序,打印机可能打印一段a的内容然后又去打印c...,     操作系统的一个功能就是将这种无序变得有序。  重点知识:    #一 操作系统的作用:     1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口     2:管理、调度进程,并且将多个进程对硬件的竞争变得有序    #二 多道技术:     1.产生背景:针对单核,实现并发     ps:     现在的主机一般是多核,那么每个核都会利用多道技术     有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个     cpu中的任意一个,具体由操作系统调度算法决定。

     2.空间上的复用:如内存中同时有多道程序     3.时间上的复用:复用一个cpu的时间片        强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样       才能保证下次切换回来时,能基于上次切走的位置继续运行

 二:进程   进程:正在运行的程序,CPU最小的资源单位。(进程是活的,一个动态的,暂时的)    开启一个进程就会在内存中开辟一块内存空间,进程与进程之间相互独立,隔离。   程序:就是一堆代码,是一个静态概念,死的,永久的   ps:进程的调度:(我们要知道的有两个)      1,时间片轮转法        2,多级反馈队列

   1,进程的并行与并发     并行:是两者同时执行,即同时进行,例如两人赛跑,都在不停的往前跑     并发:看起来像同时进行,而实质是交替轮流进行,       并发的本质:切换+保存状态(也印证了多道技术中的时间复用的特点)

   2,程序运行的三种状态:     阻塞态:遇到IO操作,sleep,input,output,recv,等都是阻塞态     就绪态:等待运行     运行态:程序正在运行的状态

    针对任务的提交方式:      同步:就是一个任务等待另外一个任务的结果,期间不做任何事情,拿到结果再去进行下一步操作     异步:是一个任务不需要等待另一个任务的结果,去执行下一步操作,等有结果时再通过异步回调去执行下一步操作。

     同步:例子:例如在银行排队办业务;     异步:就像抽号后,用户可以去在一边休息,后者(等待别人通知)就是异步等待消息通知,    针对程序的状态:     阻塞:阻塞态     非阻塞:即就绪态和运行态   3,进程的创建    新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的。       在windows中该系统调用是:CreateProcess,CreateProcess既处理进程的创建,也负责把正确的程序装入新进程。     对于windows系统来说,从一开始父进程与子进程的地址空间就是不同的。即在物理层面的隔离   4,退出进程:     1,单击×。2,正常退出,3出错退出。4,杀死进程(在cmd中输入 tasklist |findstr 进程名称;               taskkill /F /PID 进程号;)

   5,开启进程的两种方式:     1,第一种:     使用process模块创建进程      在一个python进程中开启子进程,start方法和并发效果

      import time      from multiprocessing import Process

      def f(name):       print(‘%s是子进程‘% name)       time.sleep(1)       print(‘% s子进程结束了‘ % name)

      if __name__ == ‘__main__‘:       t = Process(target=f, args=(‘gan‘,))       t.start()       #t.join()          jion方法,等待子进程结束,在进行主进程代码       time.sleep(1)       print(‘主结束了‘)     2,第二种:       自己定义一个MyProcess类去继承Process,在初始化,       from multiprocessing import Process       import os       class MyProcess(Process):        def __init__(self,name):         super().__init__()   # 初始父类不传参数         self.name = name        def run(self):         print(os.getpid())      # 获取子进程号 三个进程号都不一样         print(‘%s在那条胡同,遇见一个...‘% self.name)

       if __name__ == ‘__main__‘:       # windoss必须放在此条件下面        p1 = MyProcess(‘张三丰‘)   # 实例化参数进程对象        p2 = MyProcess(‘田七‘)        p3 = MyProcess(‘念奴娇‘)

        #p1.daemon= True   # 将p1设置为呆萌进程,必须再start()之前设置

        p1.start()     #start会自动调用run        p2.start()        p3.start()        p1.join()     # jion 将并发变为串行执行,保证数据安全        p2.join()        p3.join()        print(‘主‘)      ps:        1 p.start():启动进程,并调用该子进程中的p.run()        2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法         3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁       4 p.is_alive():如果p仍然运行,返回True       5 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)

     3,进程对象其他方法:       1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置       2 p.name:进程的名称       3 p.pid:进程的pid       4 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)       5 p.getpid()    获取子进程号       6 p.getppid()   获取父进程号       7 print(p.is_alive()) # 判断进程是否存活      结果为True     4,开启多个进程       from multiprocessing import Process       import os       def f(n):        print(‘子进程id‘,os.getpid(), ‘父进程id‘, os.getppid())        return n*n       if __name__ == ‘__main__‘:        print(‘主进程id‘)        p_list = []        for i in range(10):         p = Process(target=f, args=(i,))         p.start()         p_list.append(p)      多个进程同时运行(注意,子进程的执行顺序不是根据启动顺序决定的)        [p.join() for p in p_list]   # 列表推导式   join方法的应用        print(‘主‘)     5,多进程之间锁的使用      抢票案列:       #并发运行,效率高,但竞争写同一文件,数据写入错乱       from multiprocessing import Process,Lock       import random       def search():        dic=json.load(open(‘db‘))        print(‘\033[43m剩余票数%s\033[0m‘ %dic[‘count‘])       def get():        dic=json.load(open(‘db‘))        time.sleep(random.random()) #模拟读数据的网络延迟        if dic[‘count‘] >0:         dic[‘count‘]-=1         time.sleep(random.random()) #模拟写数据的网络延迟         json.dump(dic,open(‘db‘,‘w‘))         print(‘\033[32m购票成功\033[0m‘)        else:         print(‘\033[31m购票失败\033[0m‘)       def task(lock):        search()        lock.acquire()      抢锁        get()        lock.release()      释放锁       if __name__ == ‘__main__‘:        lock = Lock()           #生成锁对象        for i in range(100): #模拟并发100个客户端抢票         p=Process(target=task,args=(lock,))         p.start()        #加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,         即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。        虽然可以用文件共享数据实现进程间通信,但问题是:        1.效率低(共享数据基于文件,而文件是硬盘上的数据)        2.需要自己加锁处理        #因此我们最好找寻一种解决方案能够兼顾:         1、效率高(多个进程共享一块内存的数据)         2、帮我们处理好锁问题。        这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。       IPC通信机制:队列和管道         队列和管道都是将数据存放于内存中        队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,        我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,        避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。     6,进程之间相互通信      1,队列:(先进先出)        ps: 进程之间相互通信是通过队列来实现的Queue  JinableQueue       队列:管道+锁   一般进程之间都是选择队列通信,自己手动加锁会出现死锁现象       管道:管道中的数据取完就完了       队列queu:        从队列中增加值,q.put()  但队列中的值满了时,向其中增值时,会处于等待,也可以说是阻塞        从队列中获取值,q.get()  但队列中的值取空时,向其中取值时,会处于等待,也可以说是阻塞        生成一个队列对象,q = Queue()        q.close()         关闭队列,防止队列中加入更多数据       下面三种方法只适合在单进程中使用:        q.qsize()         返回队列中目前项目的正确数量        q.empty()         如果调用此方法时 q为空,返回True。        q.full()         如果q已满,返回为True. 否则为Flase      队列案列:       from multiprocessing import Queue       q=Queue(3)   #半连接数       #put ,get ,put_nowait,get_nowait,full,empty       q.put(3)       q.put(3)       q.put(3)       # q.put(3)   # 如果队列已经满了,程序就会停在这里,等待数据被别人取走,再将数据放入队列。            # 如果队列中的数据一直不被取走,程序就会永远停在这里。       try:        q.put_nowait(3) # 可以使用put_nowait,如果队列满了不会阻塞,但是会因为队列满了而报错。       except: # 因此我们可以用一个try语句来处理这个错误。这样程序不会一直阻塞下去,但是会丢掉这个消息。        print(‘队列已经满了‘)       # 因此,我们再放入数据之前,可以先看一下队列的状态,如果已经满了,就不继续put了。       print(q.full()) #满了       print(q.get())       print(q.get())       print(q.get())       # print(q.get()) # 同put方法一样,如果队列已经空了,那么继续取就会出现阻塞。       try:        q.get_nowait(3) # 可以使用get_nowait,如果队列满了不会阻塞,但是会因为没取到值而报错。       except: # 因此我们可以用一个try语句来处理这个错误。这样程序不会一直阻塞下去。        print(‘队列已经空了‘)       print(q.empty()) #空了      2,进程利用队列:
         补充:              full(),  q.empty(),   q.get_nowait()  都不适用于多进程的情况下

        案列:  from multiprocessing import Process,Queue                  def scz(q):                   要把队列的对象传进来*****                      q.put(‘hello‘)                  def xfz(q):                      print(q.get())

                if __name__ == ‘__main__‘:                    q = Queue()                    p = Process(target=scz,args=(q,))                    p1 = Process(target=xfz,args=(q,))                    p.start()                    p1.start()        总结:两个进程之间通信,是通过队列来实现的,把 产生的数据放在队列中,让另一个进程提取                在这里要注意的是要把队列对象作为参数分别传给两个进程
     7, 生产者消费者模型:    生产者:生成或者制造数据的一方    消费者:处理数据的一方    问题:解决供需不平衡的问题,用到队列来处理            案列:(不能让阻塞在data = q.get()位置)        from multiprocessing import Process,JoinableQueue,Queue        import time        import random

        def scz(name,food,q):            for i in range(0,10):                data = (‘%s生产了%s包子%s‘% (name,food,i))                time.sleep(0.5)                q.put(data)                print(data)

        def xfz(name,q):            while True:                data = q.get()                if data == None: break    # 如果data为None,说明队列中的数据已被取完                print(‘%s 吃掉了%s包子‘% (name,data))                time.sleep(random.random())                q.task_done()   # 告诉队列从队列中已取出一个数据,并且已经全部处理完毕,结束任务  *****

        if __name__ == ‘__main__‘:            # q = Queue()            q = JoinableQueue()      # *******            p = Process(target=scz, args=(‘111‘, ‘牛肉馅‘, q))            p1 = Process(target=scz, args=(‘盘龙‘, ‘白菜馅‘, q))            c = Process(target=xfz, args=(‘开门‘, q))            c1 = Process(target=xfz, args=(‘芝麻‘, q))            c.daemon = True            c1.daemon = True            p.start()            p1.start()

            c.start()            c1.start()            #这种方法太low了            # p.join()    # 确保生产者确确实实生产完了            # p1.join()   #  确保生产者确确实实生产完了            # q.put(None)   # 生产者生产完在队列增加一个值  None, 当取值取到None时说明队列中的数据取完了            # q.put(None)    # 一个消费者用一个None,两个消费者就得用两个None ,一个消费者只要接受到none,立马结束!            # 高级方法            p.join()    # 确保生产者确确实实生产完了            p1.join()

            q.join()   # 等到队列中的数据全部被取出           8,进程池与异步回调:*******

  

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

时间: 2024-10-10 20:51:37

并发编程总结一,进程的相关文章

并发编程之多进程进程进程

Python 并发编程之多进程 1.1 multiprocessing 模块 Python 中的多线程无法利用多核资源,如果想要充分的使用多核 cpu 的资源,在 Python 中大部分情况需要使用多进程. Python 为我们提供了非常好用的多进程包multiprocessing! os.cpu_coutn() multiprocessing模块用来开启子进程,并在模块中执行我们定制的任务(如函数,实现功能等). multiprocessing 模块的功能有很多: ?支持子进程 ?通信和共享数

Python3 与 C# 并发编程之~ 进程先导篇

Linux专项¶ 先写几个问号来概况下今天准备说的内容:(谜底自己解开,文中都有) 你知道Ctrl+C终止进程的本质吗?你知道Kill -9 pid的真正含义吗? 你知道那些跨平台框架(Python,NetCore)在Linux下创建进程干了啥? 你了解僵尸进程和孤儿进程的悲催生产史吗?孤儿找干爹,僵尸送往生想知道不? 想知道创建子进程后怎么李代桃僵吗?ps aux | grep xxx的背后到底隐藏了什么? 你了解Linux磁盘中p类型的文件到底是个啥吗? 为什么要realase发布而不用de

【python进阶】并发编程-线程与进程

并发编程-进程与线程 什么是进程(process)? 进程(process),是计算机中已运行程序的实体,是线程的容器:一个进程至少有一个线程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是不是在程序A读取数据的过程中,让程序B去执行,当程序A读取完数据之后,让 程序B暂停,然后让程序A继续执行?当然没问题,但这里有一个关键词:切换既然是切换,那么这就涉及到了状态的保存

并发编程基础之进程

目录 1.操作系统发展史 2.多道技术 3.并发与并行 4.进程 5.同步与异步 6.阻塞与非阻塞 7.进程的三种状态 1.操作系统发展史 研究并发编程其实就是研究操作系统的底层原理,所以我们需要从操作系统的发展史开始学起 手工操作-- 穿孔卡片 1946年第一台计算机诞生-–20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制台开关启动程序针对数据运行

JAVA 并发编程-线程与进程的由来(一)

在学习Java编程之初,我们就接触过Java线程,当时敲过代码也总结过,但是现在看来还是有点缺陷,并没有联系线程的由来来说明问题,只是简单的介绍了什么是进程,什么是线程,以及它们之间的关系-<Java-线程>.今天我们从进程和线程的由来来补充一下之前的总结. 参考:http://www.cnblogs.com/dolphin0520/p/3910667.html 一.操作系统中为什么会出现进程? 说起进程的由来,我们需要从操作系统的发展历史谈起. 最初计算机: 也许在今天,我们无法想象在很多年

49_并发编程-线程-守护进程

一.守护线程 1. 对主进程来说,运行完毕指的是主进程代码运行完毕 2. 对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕 详解: <1>主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束 <2>主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收).因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程

并发编程之守护进程

主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children 注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止 import multiprocessing import time def taks_one(): print("zi run") time.sleep(3) print(

Python并发编程之进程2

引言 本篇介绍Python并发编程下的进程,先介绍进程的相关知识,然后对python中multiprocessing模块进行介绍(Process.Pipe.Queue以及 Lock). 进程(process) 在面向线程设计的系统(如当代多数操作系统.Linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器. 进程拥有自己独立的内存空间,所属线程可以访问进程的空间. 程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 例如,我们在PyCharm开发环境中写

漫谈并发编程(一) - 并发简介

并发编程是每个程序员进阶的必修之课,想写一个安全稳定,性能强劲的并发程序可没那么容易.我将在未来的日子里,与大家分享一个并发小白成长路上的所思所想.并发编程的思想是通的,但是例子得要是具现的,在该系列中将使用java语言用以演示. 此文作为为漫谈并发编程系列的第一篇,由于本人喜欢先论理再论事,而非先论事再论理,所以就以一篇对并发的文字描述开头了. 并发编程由来 早年的计算机中没有操作系统,在某个时间段内只支持运行一个程序,并且这个程序能访问计算机的所有资源.在这个程序完全执行完后,再执行下一个程

漫谈并发编程(一) - 并发简单介绍

并发编程是每一个程序猿进阶的必修之课,想写一个安全稳定,性能强劲的并发程序可没那么easy.我将在未来的日子里,与大家分享一个并发小白成长路上的所思所想.并发编程的思想是通的,可是样例得要是具现的,在该系列中将使用java语言用以演示. 此文作为为漫谈并发编程系列的第一篇,探本溯源,以一篇对并发的文字描写叙述开头. 并发编程由来 早年的计算机中没有操作系统,在某个时间段内仅仅支持运行一个程序,而且这个程序能訪问计算机的全部资源.在这个程序全然运行完后,再运行下一个程序. 在此时,引入并发编程的优