精华内容
下载资源
问答
  • 进程具有的特征:动态性:进程是程序的一次执行过程,是临时,有生命期,是动态产生,动态消亡并发性:任何进程都可以同其他进行一起并发执行独立性:进程是系统进行资源分配和调度一个独立单位结构性:进程...

    进程

    进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。

    1e379056d2c880d4a5764b44448fe45e.png

    进程具有的特征:

    动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的

    并发性:任何进程都可以同其他进行一起并发执行

    独立性:进程是系统进行资源分配和调度的一个独立单位

    结构性:进程由程序,数据和进程控制块三部分组成

    我们经常使用windows系统,经常会看见.exe后缀的文件,双击这个.exe文件的时候,这个文件中的指令就会被系统加载,那么我们就能得到一个关于这个.exe程序的进程。进程是“活”的,或者说是正在被执行的。

    window中打开任务管理器,可以看到当前系统中正在运行的进程,如下图:

    dfe153e1a8a3475576875e4c0db6a040.png

    线程

    线程是轻量级的进程,是程序执行的最小单元,使用多线程而不是多进程去进行并发程序的设计,是因为线程间的切换和调度的成本远远小于进程。

    我们用一张图来看一下线程的状态图:

    56e06f0a0df8a4e9d0b8beaa9cefc878.png

    线程的所有状态在java.lang.Thread中的State枚举中有定义,如:

    public enum State {

    NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;

    }

    线程几个状态的介绍:

    New:表示刚刚创建的线程,这种线程还没有开始执行

    RUNNABLE:运行状态,线程的start()方法调用后,线程会处于这种状态

    BLOCKED:阻塞状态。当线程在执行的过程中遇到了synchronized同步块,但这个同步块被其他线程已获取还未释放时,当前线程将进入阻塞状态,会暂停执行,直到获取到锁。当线程获取到锁之后,又会进入到运行状态(RUNNABLE)

    WAITING:等待状态。和TIME_WAITING都表示等待状态,区别是WAITING会进入一个无时间限制的等,而TIME_WAITING会进入一个有限的时间等待,那么等待的线程究竟在等什么呢?一般来说,WAITING的线程正式在等待一些特殊的事件,比如,通过wait()方法等待的线程在等待notify()方法,而通过join()方法等待的线程则会等待目标线程的终止。一旦等到期望的事件,线程就会再次进入RUNNABLE运行状态。

    310483f1812fb7d27706e35cf02bd516.png

    TERMINATED:表示结束状态,线程执行完毕之后进入结束状态。

    注意:从NEW状态出发后,线程不能在回到NEW状态,同理,处理TERMINATED状态的线程也不能在回到RUNNABLE状态

    进程与线程的一个简单解释

    进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握。

    1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。

    abccb741606199f6f0c37779e84d64dd.png

    2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。

    eafe085ac8633bf6a3236451eba3154c.png

    3.进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。

    76091841fc3c0f8e8b40c7ece5974b79.png

    4.一个车间里,可以有很多工人。他们协同完成一个任务。

    78c6f5c21b8b99d69ff875a0d510af50.png

    5.线程就好比车间里的工人。一个进程可以包括多个线程。

    d29060d7cc82e4c77d39208724468178.png

    6.车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。

    c75e3916f6e028da0ffda7ab156af79c.png

    7.可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。

    02e4dc4ce6b1116ce3b1e1db63da0eaf.png

    8.一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。

    665d889a0fa4fb536c1e0663bcb20fa2.png

    9.还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。

    644d6cd8d9d84a7e124cae2258adcf68.png

    10.这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。

    efd4b769cd539ba86f04130ed9dd2382.png

    11.操作系统的设计,因此可以归结为三点:

    (1)以多进程形式,允许多个任务同时运行;

    (2)以多线程形式,允许单个任务分成不同的部分运行;

    (3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

    展开全文
  • 前言:单道程序和多道程序、进程和线程的区别 目录 一、进程的定义 ...这决定了通常的程序是不能参与并发执行的。因为程序的结果是不可再现的。这样程序的运行也就失去了意义。为使程序能并发执行,并且为...

    前言:单道程序和多道程序进程和线程的区别

    目录

    一、进程的定义

    1.1 定义

    1.2 基本状态

    1.3 扩展状态

    二、PCB

    2.1 内容


    一、进程的定义

    在多道程序环境下,程序的执行属于并发执行,此时它们将失去封闭性,并具有间断性不可再现性的特征。这决定了通常的程序是不能参与并发执行的。因为程序的结果是不可再现的。这样程序的运行也就失去了意义。为使程序能并发执行,并且为了对并发执行的程序加以描述和控制,就此引入了“进程”的概念。

    1.1 定义

    进程是进程实体运行过程,是系统进行资源分配和调度的一个独立单位。进程实体(进程映像)由程序段、相关的数据段和PCB三部分构成。由创建而产生,由调度而执行,由撤销而消亡。

    1.2 基本状态

    就绪(Ready)、执行阻塞。从执行→阻塞的典型事件有:请求I/O,申请缓存空间,请求访问某临界资源等。而事件是指进程由执行状态转变为阻塞状态所等待发生的时间,即阻塞原因

    1.3 扩展状态

    最重要的是,挂起。原因有:终端用户的请求、父进程的请求、负荷调节的需要、操作系统的需要。操作系统有时需要挂起某些进程,以便检查运行中的资源使用情况。 

    Readya/Readys、Blocka/Blocks。活动就绪和静止就绪、活动阻塞和静止阻塞相互转化。

    创建, 分两步:首先为进程创建PCB填写必要的管理信息;其次,把该进程转入就绪状态并插入就绪队列之中。引入创建状态是为了保证进程的调度必须在创建工作完成后进行,以确保对进程控制块操作的完整性。根据系统性能或主存容量的限制推迟创建进程的提交。

    终止,分两步:1等待操作系统进行善后处理,然后将其PCB清零,并将PCB空间返还系统。

    二、PCB

    2.1 内容

    PCB记录了操作系统所需的、用于描述进程当前情况以及控制进程运行的全部信息。使得一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程。

    OS要调度某进程执行时,要从该进程PCB中查出其现行状态及优先级;在调度到某进程后,要根据PCB中所保存的处理机状态信息,设置该进程恢复运行的现场,并根据其PCB中的程序和数据的内存地址,找到其程序和数据; 执行时,当需要完成进程间同步、通信或访问文件,也需要访问PCB;阻塞时,又必须将其断点的处理机环境保存在PCB中。可见,在进程的整个生命周期中,系统总是通过PCB对进程进行控制的。PCB是进程存在的唯一标志。

    进程被创建时,系统为其分配PCB;进程结束时又回收PCB,进程于是也随之消亡(僵死进程)。PCB可以被操作系统中的多个模块读或修改,如被调度程序、资源分配程序、中断处理程序以及监督和分析程序等读或修改。因为PCB经常被系统访问,尤其是被运行效率很高的进程及分派程序访问,故PCB应该常驻内存。常驻内存的原因也是在此了。在Linux中使用task_struct来描述每个进程的进程控制块。思路和实现是允许有差别的。

    展开全文
  • 以单CPU多任务操作系统为例,当说两个程序并发执行时,是指宏观上看这两个程序同时在向前推进。例如,可以在一台单CPU单核笔记本电脑中一边运行音频播放程序听歌曲,一边用WPS 办公软件,编辑程序在工作同时音...

    现代操作系统都支持多任务,具有并发、共享、虚拟和异步性特征

    • 并发

    并发是指两个或多个事件在同一时间间隔内发生。并发强调"同一时间间隔",与并行是有区别的两个不同的概念,并行是指多个事件同时发生。

    以单CPU多任务的操作系统为例,当说两个程序并发执行时,是指宏观上看这两个程序同时在向前推进。

    例如,可以在一台单CPU单核的笔记本电脑中一边运行音频播放程序听歌曲,一边用WPS 办公软件,编辑程序在工作的同时音频播放程序也在工作。

    de9d90cc3351e3e2aa2c57b18c633e4b.png

    但是,在单CPU单核的系统中,任意时刻只能有程序流在CPU执行,要么编辑文档程序,要么是音频播放程序。之所以用户能感觉到两个程序似乎在同时工作,而且互不干扰,是因为操作系统使两个程序在CPU上快速地轮流交替执行,实现了"并发"的功能。

    • 共享

    共享是指系统中的资源可供内存中多个并发执行的进程共同使用。资源共享有两种方式,既互斥共享和同时共享。

    互斥共享是指任意时刻一种资源只能被一个进程访问,当一个进程访问资源时,其它进程必须等待,直到资源被进程访问完毕,释放访问权。

    例如打印机的访问 如果不采互斥访问的方式,可能会把多个进程的输出内容打印到同一个同一页打印纸上。

    同时,共享是指从宏观上看,资源可以被多个进程同时访问。如对磁盘的访问。

    虽然任意时刻只能有一个程序访问某一个磁盘。但是,多个程序可以在短时间内轮流访问磁盘。从用户的角度看,多个用户程序可以同时发送磁盘访问命令,并同时得到响应。从宏观上看,磁盘可以被多个用户程序同时访问。

    并发与共享的关系是相互依赖的。

    如果系统不支持并发,资源的使用都是独占的,不需要共享资源。

    另一方面,如果不能实现有效的资源共享,并发就不可能得到很好的支持

    7f785f359d7c369ee21552500cf02cbe.png
    • 虚拟

    虚拟是指通过某种技术把一个物理实体变成若干逻辑上的对应物。

    物理实体是实际存在的,而虚拟仅仅是用户感觉到的。

    • 异步性

    进程以不可预知的速度向前推进。内存中的每个程序任何执行、何时暂停、以怎样的速度向前推进,以及每道程序总共需要多长时间才能完成等,都是不可预知的。

    bd76554ac32ecdd68ac554565d0fd814.png
    展开全文
  • 什么是进程进程(Process)是计算机...并发性:任何进程都可以同其他进程一起并发执行独立性:进程是一个能独立运行基本单位,同时也是系统分配资源和调度独立单位;异步性:由于进程间相互制约,使进程具有执行...

    什么是进程

    进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

    进程的特征:

    动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。

    并发性:任何进程都可以同其他进程一起并发执行

    独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;

    异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进

    结构特征:进程由程序、数据和进程控制块三部分组成。

    多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。

    进程与程序的区别:

    程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

    而进程是程序在处理机上的一次执行过程,它是一个动态的概念。

    并发与并行

    并发:伪并行,看着像同时运行,其实是任务之间的切换(遇到IO切换的会提高代码效率),任务切换+报错状态(保存现场)

    并行:真正同时运行,应用的是多核技术(多个cpu)

    5609618660843094b5fb99ea4c7cfcbb.png

    同步\异步\阻塞\非阻塞

    1874f7e5becc0c5be92088669006018f.png

    进程的三状态:就绪(等待操作系统调度去cpu里面执行) 执行 阻塞

    同步:多个任务提交出去要排队一个任务执行完后才执行下一个是串行的

    异步 :任务的提交方式,多个任务提交出去,同时执行

    阻塞与非阻塞:

    阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的

    同步阻塞

    效率最低

    异步阻塞

    异步操作是可以被阻塞住的,只不过它不是处理消息时阻塞,而是等待消息通知时阻塞

    同步非阻塞形式

    实际上效率低下

    程序要在两种不同的行为之间来回切换

    异步非阻塞形式

    效率高

    程序不需要在两种不同的操作之间来回切换

    multiprocess模块

    Process类中参数的介绍

    group参数未使用,值始终为None

    target表示调用对象,即子进程要执行的任务

    args表示调用对象的位置参数元组,args=(1,2,'egon',)

    kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}

    name为子进程的名称

    from multiprocessing import Process

    import time

    def f1():

    time.sleep(2)

    print("xxx")

    def f2():

    time.sleep(2)

    print("kkk")

    #windows系统下必须写main,因为windows系统创建子进程的方式决定的,开启一个子进程,

    #这个子进程 会copy一份主进程的所有代码,并且机制类似于import引入,这样就容易导致引入代码的时候,

    #被引入的代码中的可执行程序被执行,导致递归开始进程,会报错

    if __name__ == '__main__':

    p1 = Process(target=f1,)

    p2 = Process(target=f2,)

    p1.start()

    p2.start()

    Process类中方法介绍:

    p.start():启动进程,并调用该进程中的p.run()

    p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类中一定要实现这方法

    p.termintate(): 强制终止进程p,不会进行任何清理操作

    p.is_alive(): 如果p仍然运行,返回True

    p.join(): 主进程等待子进程运行完才继续执行,p.join只能join住start开启的进程,而不能join住run开启的进程

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importtimefrom multiprocessing importProcessdeff1():

    time.sleep(2)print("xxx")deff2():

    time.sleep(2)print("sss")if __name__ == '__main__':

    p1= Process(target=f1,)

    p1.start()

    p1.join()#主进程等待子进程运行完才继续执行

    print("开始")

    p2= Process(target=f2,)

    p2.start()

    p2.join()print("我是主进程!!!")

    join的用法

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcessdeff1(n):print(n)if __name__ == '__main__':#p1 = Process(target=f1,args=("alex",))

    p1 = Process(target=f1,kwargs={'n':'alex'})

    p1.start()

    进程传参

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcessclassMyProcess(Process):def __init__(self,n):

    super().__init__() #执行父类的init

    self.n =ndefrun(self):print("wusir和%s在一起"%self.n)if __name__ == '__main__':

    p1= MyProcess("alex")

    p1.start()

    进程传参2

    Process类中自带封装的各属性

    p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置

    p.name:进程的名称

    p.pid:进程的pid

    windows中的Process()必须放到if __name__ == '__main__':下

    没有写就会不断的递归调用模块,导致报错

    创建进程的第二种方法(继承)

    from multiprocessing import Process

    class MyProcess(Process):

    def __init__(self,n):

    super().__init__()

    self.n = n

    def run(self):

    print("%s和alex不可告人的密码"%self.n)

    if __name__ == '__main__':

    p1= MyProcess("wusir")

    p1.start()

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcess

    n= 100

    defwork():globaln

    n=0print('子进程:',n)#0

    if __name__ == '__main__':

    p= Process(target=work,)

    p.start()

    p.join()print("主进程内",n)#100

    进程间数据是隔离的

    Process对象其他方法或属性

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcessimporttimeimportrandomclassPiao(Process):def __init__(self,name):

    self.name=name

    super().__init__()defrun(self):print("%s is piaoing" %self.name)

    time.sleep(random.randrange(1,5))print("%s is piaoing" %self.name)

    p1= Piao("alex")

    p1.start()print(p1.is_alive()) #True

    p1.terminate() #关闭进程,不会立即关闭,所以is_alive立刻查看的结果可能还是存活

    time.sleep(0.2)print("开始")print(p1.is_alive()) #False

    terminate和is_live

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcessimporttimeimportrandomclassPiao(Process):def __init__(self,name):

    super().__init__()

    self.name=namedefrun(self):print("%s is piaoing"%self.name)

    time.sleep(random.randrange(1,3))print("%s is paioing" %self.name)if __name__ == '__main__':

    p= Piao('alex')

    p.start()print("开始")print(p.pid)

    pid用法

    僵尸进程:当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程

    孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

    守护进程

    一.守护进程会在主进程代码执行结束后终止

    二.守护进程无法再开启子进程

    p.deamon = True #一定要在p.start()前添加

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importtimefrom multiprocessing importProcessdeff1():

    time.sleep(3)print('守护进程的代码')deff2():

    time.sleep(5)print("普通进程的代码")if __name__ == '__main__':

    p= Process(target=f1,)

    p.daemon= True #设置为守护进程

    p.start()

    p2= Process(target=f2,)

    p2.start()#等待p2进程结束,才进行执行下面的代码

    #p2.join()

    #守护进程会跟着父进程代码的结束而结束

    print("主程序结束")

    守护进程

    进程同步锁

    加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,串行的修改,牺牲了速度确保证了数据安全

    用文件共享数据实现进程间通信存在的问题:

    1.效率低(数据在硬盘上)

    2.需要自己加锁处理

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcess,Lockimporttimedeff1(i,lic):

    lic.acquire()

    time.sleep(1)print(i)

    lic.release()if __name__ == '__main__':

    lic=Lock()for i in range(20):

    p= Process(target=f1,args=(i,lic))

    p.start()

    互斥锁

    加锁模拟抢票

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-#先创建一个ticket.txt文件,写入{'count':1}

    importtimefrom multiprocessing importProcess,Lockdefshow_t(i):

    with open('ticket','r',encoding='utf-8') as f:

    ticket_data=f.read()

    t_data=eval(ticket_data)print("%s查询剩余票数为%s"%(i,t_data['count']))defget_t(i,l1):

    l1.acquire()

    with open('ticket','r',encoding='utf-8') as f:

    ticket_data=f.read()

    t_data=eval(ticket_data)if t_data['count'] >0:

    t_data['count'] -= 1

    print("%s抢票成功"%i)

    time.sleep(0.2)

    with open('ticket','w') as f:

    f.write(str(t_data))else:print('没票了!!!')

    l1.release()if __name__ == '__main__':

    l1=Lock()for i in range(10):

    p1= Process(target=show_t,args=(i,))

    p1.start()for i in range(10):

    p2= Process(target=get_t,args=(i,l1))

    p2.start()

    抢票程序

    队列

    进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的。队列就像一个特殊的列表,但是可以设置固定长度,并且从前面插入数据,从后面取出数据,先进先出。

    1 队列和管道都是将数据存放于内存中

    2 队列基于(管道+锁)实现,

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcess ,Queue

    q= Queue(3)

    q.put(1)print(">>>>>:",q.qsize())#返回当前队列的内容长度

    print(q.full())

    q.put(2)print(">>>>>:",q.qsize())

    q.put(3)print(q.full())try:

    q.put_nowait(4) #queue.Full

    except:print("满了")print(q.get())print(q.get())print(q.get())print("是不是不空",q.empty())try:

    q.get_nowait()#queue.Empty

    except:print("队列空了")print("那多了")

    其他

    q =Queue([maxsize]) 创建共享的进程队列。maxsize是队列中允许的最大项数。

    q.get() 返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止

    q.get_nowait( ) 不等待,会报错

    q.put_nowait( ) 不等待,会报错

    q.put() 将item放入队列。如果队列已满,此方法将阻塞至有空间可用为止。

    q.qsize() 返回队列中目前项目的正确数量。

    q.empty() 如果调用此方法时 q为空,返回True。

    q.full() 如果q已满,返回为True. 由于线程的存在,结果也可能是不可靠的。

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcess,Queuedeff1(q):

    q.put("约吗")if __name__ == '__main__':

    q=Queue(3)

    p= Process(target=f1,args=(q,))

    p.start()

    son_p_msg=q.get()print("来自进程的消息:",son_p_msg)

    基于队列的通信

    Manager模块

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importtimefrom multiprocessing importProcess,Lock,Managerdeff1(m_d,l1):

    with l1:

    tmp= m_d['num']

    tmp-= 1time.sleep(0.1)

    m_d['num'] =tmpif __name__ == '__main__':

    m=Manager()

    l1=Lock()

    m_d= m.dict({'num':100})

    p_list=[]for i in range(10):

    p= Process(target=f1,args=(m_d,l1))

    p.start()

    p_list.append(p)

    [pp.join()for pp inp_list]print(m_d['num'])

    修改进程共享数据

    生产者消费者模型

    在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    from multiprocessing importQueue,Processimporttimedefproducer(q):for i in range(10):

    time.sleep(0.7)

    s= '大包子%s号'%iprint(s+'新鲜出炉')

    q.put(s)defconsumer(q):while 1:

    time.sleep(1)

    baozi=q.get()print(baozi+"被吃了")if __name__ == '__main__':

    q= Queue(10)

    pro_p= Process(target=producer,args=(q,))

    con_p= Process(target=consumer,args=(q,))

    pro_p.start()

    con_p.start()

    low版,不能推迟

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    from multiprocessing importQueue,Processimporttimedefproducer(q):for i in range(10):

    time.sleep(0.7)

    s= '大包子%s号'%iprint(s+'新鲜出炉')

    q.put(s)

    q.put(None)defconsumer(q):while 1:

    time.sleep(1)

    baozi=q.get()if baozi ==None:print("都吃完了")break

    print(baozi+"被吃了")if __name__ == '__main__':

    q= Queue(10)

    pro_p= Process(target=producer,args=(q,))

    con_p= Process(target=consumer,args=(q,))

    pro_p.start()

    con_p.start()

    None判断版

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    from multiprocessing importQueue,Processimporttimedefproducer(q):for i in range(10):

    time.sleep(0.7)

    s= '大包子%s号'%iprint(s+'新鲜出炉')

    q.put(s)defconsumer(q):while 1:

    time.sleep(1)try:

    baozi= q.get_nowait()#不合适,因为无法确定做的块,还是吃的块,如果按照这样的写法,你吃的快的话,那么这个消费者的程序就直接结束了,不能满足需求

    exceptException:break

    print(baozi+"被吃了")if __name__ == '__main__':

    q= Queue(10)

    pro_p= Process(target=producer,args=(q,))

    con_p= Process(target=consumer,args=(q,))

    pro_p.start()

    con_p.start()

    升级版

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importtimefrom multiprocessing importProcess,Queue,JoinableQueuedefproducer(q):for i in range(10):

    time.sleep(0.2)

    s= "大包子%s号"%iprint(s+"新鲜出炉")

    q.put(s)

    q.join()#就等着task_done()信号的数量,和我put进去的数量相同时,才继续执行

    print("所有数据处理完毕")defconsumer(q):while 1:

    time.sleep(0.3)

    baozi=q.get()print(baozi+"被吃了")

    q.task_done()#给队列发送一个取出的这个任务已经处理完毕的信号

    if __name__ == '__main__':

    q= JoinableQueue(30)

    pro_p= Process(target=producer,args=(q,))

    con_p= Process(target=consumer, args=(q,))

    pro_p.start()

    con_p.daemon=True

    con_p.start()

    pro_p.join()print("主进程结束")

    终极版

    JoinableQueue([maxsize])

    maxsize是队列中允许最大项数,缩略无大小限制

    q.task_done() 消费者使用此方法发出信号,表示q.get()的返回项目已经被处理了,如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常

    q.join() 生产者调用此方法进行阻塞,直到队列中所有项目被处理.阻塞将持续到队列中的每个项目均调用q.task_done()方法为止

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcess,JoinableQueueimporttime,random,osdefconsumer(q):whileTrue:

    res=q.get()

    time.sleep(random.randrange(1,3))print('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res))

    q.task_done()defproducer(name,q):for i in range(10):

    time.sleep(random.randrange(1,3))

    res='%s%s' %(name,i)

    q.put(res)print('\033[44m%s 生成了 %s\033[0m' %(os.getpid(),res))

    q.join()if __name__ == '__main__':

    q=JoinableQueue()

    p1= Process(target=producer, args=('包子',q))

    p2= Process(target=producer, args=('馒头', q))

    p3= Process(target=producer, args=('alex', q))

    c1= Process(target=consumer,args=(q,))

    c2= Process(target=consumer,args=(q,))

    c1.deamon=True

    c2.deamon=True

    p_1=[p1,p2,p3,c1,c2]for p inp_1:

    p.start()

    p1.join()

    p2.join()

    p3.join()print("主程序")

    View Code

    管道

    进程间的通信

    Pipe([duplex]) 在进程之间创建一条通道,管道默认全双工的

    conn1.recv() 接收conn2.send(obj)发送的对象.

    conn1.send(obj) 通过连接发送对象

    conn1.close() 关闭连接

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    from multiprocessing importProcess,Pipedeff1(conn):

    from_qian=conn.recv()print("我是子进程")print("来自主进程的消息:",from_qian)if __name__ == '__main__':

    conn1,conn2= Pipe()#创建一个管道对象,全双工,返回管道的两端,但是一端发送的消息,只能另外一端接收,自己这一端是不能接收的

    #可以将一端或者两端发送给其他的进程,那么多个进程之间就可以通过这一个管道进行通信了

    p1 = Process(target=f1,args=(conn2,))

    p1.start()

    conn1.send('小宝贝')print("主进程")

    管道通信

    信号量

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    importtimeimportrandomfrom multiprocessing importProcess,Semaphoredeff1(i,s):

    s.acquire()print("%s男嘉宾到了"%i)

    time.sleep(random.randint(1,3))

    s.release()if __name__ == '__main__':

    s= Semaphore(4) #计数器4,acquire一次减一,为0,其他人等待,release加一

    for i in range(10):

    p= Process(target=f1,args=(i,s))

    p.start()

    Semaphore

    事件

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    from multiprocessing importProcess,Event

    e=Event()print("e的状态",e.is_set())

    e.set()#将e的状态改为True

    print("e的状态",e.is_set())

    e.clear()#将e的转态改为False

    e.wait() #e这个事件对象如果为False,就在我加wait的地方等待

    print("进程过了wait")

    Event

    进程池

    p.apply() #同步方法

    p.apply_async() #异步方法

    p.close() 关闭进程池,防止进一步操作

    p.join() 等待所有工作进程退出

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    importtimefrom multiprocessing importProcess,Pool#def f1(n):#time.sleep(1)#print(n)#对比多进程和进程池的效率

    deff1(n):for i in range(5):

    n= n +iif __name__ == '__main__':#统计进程池进行100个任务的时间

    s_time =time.time()

    pool= Pool(4) #里面这个参数是指定进程池中有多少个进程用的,4表示4个进程,如果不传参数,默认开启的进程数一般是cpu的个数

    #pool.map(f1,[1,2]) #参数必须是可迭代的

    pool.map(f1,range(100)) #参数数据必须是可迭代的,异步提交任务时自带join功能

    e_time =time.time()

    dif_time= e_time -s_time#统计100个进程,来执行100个任务的时间

    p_s_t = time.time()#多进程起始时间

    p_list =[]for i in range(100):

    p= Process(target=f1,args=(i,))

    p.start()

    p_list.append(p)

    [pp.join()for pp inp_list]

    p_e_t=time.time()

    p_dif_t= p_e_t -p_s_tprint("进程池的时间:",dif_time)print('多进程的执行时间:',p_dif_t)

    进程池的map方法

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importtimefrom multiprocessing importProcess,Pooldeff1(n):

    time.sleep(1)return n*nif __name__ == '__main__':

    pool= Pool(4)for i in range(10):print("xxxx")

    res= pool.apply(f1,args=(i,))print(res)

    进程池的同步方法

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importtimefrom multiprocessing importProcess,Pooldeff1(n):

    time.sleep(0.5)return n*nif __name__ == '__main__':

    pool= Pool(4)

    res_list=[]for i in range(10):print("xxxx")#异步给进程池提交任务

    res = pool.apply_async(f1,args=(i,))

    res_list.append(res)#print("等待所有任务执行完")

    #pool.close() #锁住进程池,意思就是不让其他的程序再往这个进程池里面提交任务了

    #pool.join()

    #打印结果,如果异步提交之后的结果对象

    for i inres_list:print(i.get())

    进程池的异步方法

    回调函数

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    #-*- coding:utf-8 -*-

    importosfrom multiprocessing importPool,Processdeff1(n):print('进程池里面的进程id',os.getpid())print('>>>>',n)return n*ndefcall_back_func(f):print(">>>>>>>>>>>",os.getpid())print("回调函数的结果",f)if __name__ == '__main__':

    pool= Pool(4)

    res= pool.apply_async(f1,args=(5,),callback=call_back_func)

    pool.close()

    pool.join()print('子进程的id',os.getpid())

    callback

    展开全文
  • java线程创建_笔记

    2018-03-05 22:41:21
    进程的概念:进程是处于运行过程中...并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。线程的概念:线程是进程的执行单元。1. 线程在程序中是独立的...
  • 进程具有的特征:动态性:进程是程序的一次执行过程,是临时,有生命期,是动态产生,动态消亡并发性:任何进程都可以同其他进行一起并发执行独立性:进程是系统进行资源分配和调度一个独立单位结构性:进程...
  • 进程概念的引入我们都知道:操作系统(OS)的基本特征是...而程序的概念不能描述程序在内存中的运行状态,由此引入进程的概念,即描述程序在内存中的执行时的动态特征,也就是在执行的程序,一个具有独立功能的程序...
  • 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进结构特征:进程由程序、数据和进程控制块三部分组成。多个不同的进程可以包含相同的程序:一个程序在不同...
  • 为了使程序能够并发执行,并且可以对并发执行的程序加以描述和控制,引入了“进程”的概念。 为了使参与并发执行的每个程序(含数据)能够独立运行,在操作系统中必须为之配备一个专门的数据结构,称...
  • 什么是进程进程(Process)是计算机...并发性:任何进程都可以同其他进程一起并发执行独立性:进程是一个能独立运行基本单位,同时也是系统分配资源和调度独立单位;异步性:由于进程间相互制约,使进程具有执行...
  • 前言“本期带来的文章是python中多线程与threading模块的主要内容。主要分为「并发与并行」,「进程与线程」,「python实现多线程」三块内容。...其中正是因为系统中的程序能「并发执行」这一特征,才...
  • (内有最新习题和ppt教程) 最新二级公共基础知识填空40题+80选择题 (1) 算法复杂度主要包括______复杂度和空间复杂度。...(41) 在下列选项中,哪个不是一个算法一般应该具有的基本特征______。(C)...
  • (41) 在下列选项中,哪个不是一个算法一般应该具有的基本特征(C) A. 确定性 B. 可行性 C. 无穷性 D. 拥有足够情报 (42) 希尔排序法属于哪一种类型排序法(B) A.交换类排序法 B.插入类排序法 C.选择类排序法 D.建...
  • 6、 操作系统是一个大型的程序系统,它负责计算机的全部软、硬件资源的分配、调度工作,控制并协调并发活动,实现信息的存取和保护。它提供用户接口,使用户获得良好的工作环境。操作系统使整个计算机系统实现了高...
  • 线程及其生命周期

    2020-12-07 09:25:36
    进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。 进程具有特征: 动态性...
  • 并发执行和多线程 alpaka:并行内核加速抽象库。 ArrayFire:通用GPU库。 Async++:C++ 11 轻量级并行框架,受Microsoft PPL库和N3428 C++标准提案启发。 Boost.Compute :用于OpenCLC++GPU计算库。 ...
  • Invoke:用于管理面向 shell 的子进程,同时支持将可执行的 Python 代码组织成命令行可调用的状态。 tmuxp: tmux 会话管理器。 高级 CLI httpie:一个命令行 HTTP 客户端,cURL 的替代品,易用性更好。 i...
  • the fastest in-memory index in the East 东半球最快并发索引 、知识图谱车音工作项目、自然语言生成资源大全 、中日韩分词库mecabPython接口库、中文文本摘要/关键词提取、汉字字符特征提取器 (featurizer),...
  • springCloud

    2018-08-09 16:54:33
    设计代理目的就是为了能够从应用程序中传入消息,并执行一些特别操作。 和组织间网络通信。设计代理目的就是为了能够从应用程序中传入消息,并执行一些特别操作。 现有消息代理开源产品: ActiveMQ ...
  • 如果对C语言较熟悉并具有某些应用Unix的经验,那么对阅读本书是非常有益的,但是并不要求读者具有Unix的程序设计经验。本书面向的主要读者是:熟悉Unix的程序员,熟悉某个其它操作系统的程序员,他们希望了解大多数...
  • asp.net知识库

    2015-06-18 08:45:45
    完整在.net后台执行javascript脚本集合 ASP.NET 中正则表达式 常用匹配正则表达式和实例 经典正则表达式 delegate vs. event 我是谁?[C#] 表达式计算引擎 正式发布表达式计算引擎WfcExp V0.9(附源码) 运算...
  • 8.1.3 更大的程序规模 159 8.2 包规范 159 8.3 无主体包 162 8.4 包主体 163 8.5 %TYPE和%ROWTYPE 166 8.6 模块化编程 168 8.7 重载 171 8.8 增强安全性 173 8.9 定义者和调用者权限 176 8.10 可下载代码 ...
  • 8.1.3 更大的程序规模 159 8.2 包规范 159 8.3 无主体包 162 8.4 包主体 163 8.5 %TYPE和%ROWTYPE 166 8.6 模块化编程 168 8.7 重载 171 8.8 增强安全性 173 8.9 定义者和调用者权限 176 8.10 可下载代码 ...
  • Qt程序嵌入浏览器中网页中文本框等控件输入。 迷你模式,界面大小随意设置,采用布局自使用任何分辨率。 纯数字键盘模式,自由控制弹出完整输入法面板和数字键盘面板,只需要对控件设置属性即可。例如ui->...
  • 复旦nois教材01.rar

    2009-08-05 20:08:37
    1.4 支持Nios CPUFPGA型号.............................................................................................5 第二章 SOPC Builder开发环境.......................................................

空空如也

空空如也

1 2
收藏数 25
精华内容 10
关键字:

并发执行的程序具有_____特征