python_多进程_multiprocessing

1、进程的概念

什么是进程—>CPU在同一时刻只能处理一个任务,只是因为cpu执行速度很快。 
cpu在各个任务之间来回的进行切换。 
进程的概念:正在进行的一个过程或者说一个任务,而负责执行任务的则是CPU,进程本身是 一个抽象的概念,即进程就是一个过程、一个任务。 
CPU描述的是一个程序的执行过程. 
进程之间是如何做到并发的:CPU在各个任务之间来回的进行切换,并在切换的过程当中保存当前进程的执行状态(保存蛋糕的执行过程)。 
进程与程序的区别:程序相当于菜谱,而进程相当于做菜的整个过程。 
需要强调的是:同一个程序执行两次(双击),那也是两个进程,比如打开暴风影音,虽然都是同一个软件,但是一个可以播放a,一个可以播放b. 
核的概念:https://zhidao.baidu.com/question/541410131.html 
处理器,就是说有几个处理器。。。也就说一个CPU里面会有几个处理器,这样就可以同时处理几个要求了。。。

2、并行与并发的区别

无论是并行还是并发,在用户看来都是同时运行的,不管是进程还是线程,都只是一个任务而已, 真正干活的是CPU,CPU来做这些任务,而一个cpu(单核)同一时刻只能执行一个任务。 
并行:多个任务同时运行,只有具备多个cpu才能实现并行,含有几个cpu,也就意味着在同一时刻可以执行几个任务。 
并发:是伪并行,即看起来是同时运行的,实际上是单个CPU在多道程序之间来回的进行切换。

3、同步与异步的概念

同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去。 
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进行处理,这样可以提高执行的效率。 
打电话的过程就是同步通信,发短信时就是异步通信。

4、进程创建的方式

用户创建出来的所有进程都是由操作系统负责的,因此无论是哪一种创建进程的方式,实际上都是调用操作系统的接口创建的,进程的切换都是由操作系统控制的。 
无论哪一种创建进程的方式,新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的。

5、父进程和子进程之间的关系

子进程创建后,父进程和子进程有各自不同的地址空间,多道技术要求物理层面实现进程之间内存的隔离,任何一个进程在其地址空间的修改都不会影响到另外一个进程。 
注意:子进程和父进程之间是可以有只读的共享的内存区域的。 
进程与进程之间数据(资源)是隔离的,两个进程之间可以基于管道这种方式进行通信。在Unix当中,是含有进程层次的概念的,但是在windows当中,是没有进程层次的概念的,所有的进程都是地位相同的。 
在Linux当中,每启动一个命令,都会启动一个进程。

6、线程的相关概念

1 线程的概念 
一个进程里面至少有一个控制线程,进程的概念只是一种抽象的概念,真正在CPU上面调度的是进程里面的线程,就好比真正在地铁这个进程里面工作的实际上是地铁里面的线程,北京地铁里面至少要有一个线程,线程是真正干活的,线程用的是进程里面包含的一堆资源,线程仅仅是一个调度单位,不包含资源。

3 什么时候需要开启多个线程? 
什么时候需要开启多个线程:一个进程里面的多个线程共享这个进程里面的资源,因此如果多个任务共享同一块资源的时候,需要开启多个线程。 
多线程指的是,在一个进程中开启多个线程,简单的说:如果多个任务共用同一个资源空间,那么必须在一个进程内开启多个线程。

4 一个进程里面需要包含多个线程? 
一个进程这个任务里面可能对应多个分任务,如果一个进程里面只开启一个线程的话,多个分任务之间实际上是串行的执行效果,即一个程序里面只含有一条执行路径。

5 多线程和多进程的关系 
对于计算密集型应用,应该使用多进程;对于IO密集型应用,应该使用多线程。 
线程的创建比进程的创建开销小的多。

6 Python中线程的特点 
在其他语言当中,一个进程里面开启多个线程,每个线程都可以给一个cpu去使用,但是在python当中,在同一时刻,一个进程当中只能有一个线程处于运行状态。 
eg:在其他语言当中,比如我现在开启了一个进程,这个进程当中含有几个线程,如果我现在有多个cpu,每一个线程是可以对应相应的CPU的。 
但是在python当中,如果我们现在开启了一个进程,这个进程里面对应多个线程,同一时刻只有一个线程可以处于运行状态。 
对于其他语言而言,在多CPU系统中,为了最大限度的利用多核,可以开启多个线程。 
但是Python中的多线程是利用不了多核优势的。

进程与线程的区别: 
在同一个进程当中,多个线程彼此之间可以相互通信;但是进程与进程之间的通信必须基于IPC这种消息的通信机制(IPC机制包括队列和管道)。 
在一个进程当中,改变主线程可能会影响其它线程的行为,但是改变父进程并不会影响其它子进程的行为,因为进程与进程之间是完全隔离的。 
在python当中,在同一时刻同一进程当中只能同时有一个线程在运行,如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起。

================================================================================================以上内容为转载

================================================================================================

以下内容为原创

1.锁

 

锁是为了确保数据一致性,比如读写锁,每个进程给一个变量增加 1 ,但是如果在一个进程读取但还没有写入的时候,另外的进程也同时读取了,并写入该值,则最后写入的值是错误的,这时候就需要锁。

测试数据(1,2,3,4,5,6,7,8,9,10)存在data文件中

不加锁

import os
from multiprocessing import  Process,Lock
import time
import random
 
def work():  # 买票
        data=[]
 
        with open('/home/user/6-StudyExcise/studyPython/data') as file:
            for line in file.readlines():
                data.append(line.replace('\n',''))
        print('剩余票数: %s' % len(data))
        if len(data)>0:
            data=data[0:len(data)-1]
            time.sleep(random.randint(110))  # 模拟网络延迟
            print(data)
            with open('/home/user/6-StudyExcise/studyPython/data','w',encoding='utf-8') as file:
                for in data:
                    file.write(i+'_10'+'\n')
            print('%s 购票成功' % os.getpid())
        else:
            print('%s 购票失败' % os.getpid())
if __name__=='__main__':
    # lock = Lock()
    p_l = []
    for in range(5):
        = Process(target=work)
        p_l.append(p)
        p.start()
    for in p_l:
        p.join()
 
    with open('/home/user/6-StudyExcise/studyPython/data') as file:
        str=file.read()
        print(str)

加锁

import os
from multiprocessing import  Process,Lock
import time
import random
 
def work(lock):  # 买票
    data=[]
    with lock:
        with open('/home/user/6-StudyExcise/studyPython/data') as file:
            for line in file.readlines():
                data.append(line.replace('\n',''))
        print('剩余票数: %s' % len(data))
        if len(data)>0:
            data=data[0:len(data)-1]
            time.sleep(random.randint(110))  # 模拟网络延迟
            print(data)
            with open('/home/user/6-StudyExcise/studyPython/data','w',encoding='utf-8') as file:
                for in data:
                    file.write(i+'_10'+'\n')
            print('%s 购票成功' % os.getpid())
        else:
            print('%s 购票失败' % os.getpid())
if __name__=='__main__':
    lock = Lock()
    p_l = []
    for in range(5):
        = Process(target=work,args=(lock,))
        p_l.append(p)
        p.start()
    for in p_l:
        p.join()
 
    with open('/home/user/6-StudyExcise/studyPython/data') as file:
        str=file.read()
        print(str

 

说明:

当多进程共享一个文件时,不加锁会导致对文件修改与实际不一致(混乱)(左图),加锁后,每个进程依次得到文件读写权限(右图)

2.join:阻塞的是主进程,比如:xx.join(),那么主进程只会在xx执行完之后才执行

#encoding:utf-8
from multiprocessing import Process
import os, time, random
 
def r1(process_name):
    for in range(5):
        print (process_name, os.getpid())     #打印出当前进程的id
        time.sleep(random.random())
def r2(process_name):
    for in range(5):
        print (process_name, os.getpid() )    #打印出当前进程的id
        time.sleep(random.random()*2)
 
if __name__ == "__main__":
        print ("main process run...")
        p1 = Process(target=r1, args=('process_name1', ))
        p2 = Process(target=r2, args=('process_name2', ))
        p1.start()
        p2.start()
        p1.join()
        p2.join()
        print ("main process runned all lines...")

 

说明:

1.执行p1.join(), p2.join(),之后,,,主线程的 print ("main process runned all lines...")才会执行,(左图)

2.p1.join(),但是p2没有执行join ,,主线程的 print ("main process runned all lines...") 在等p1执行完之后才会执行,(右图)

3.如果代码顺序如下:

p1.start()

p1.join()

p2.start()

则会在执行完p1,会执行主线程的 print ("main process runned all lines..."),最后才会执行p2,因为join是用来阻塞当前线程的,p1.start()之后,p1就提示主线程,需要等待p1结束才向下执行,那主线程就乖乖的等着啦,自然没有执行p2.start()这一句啦,当然就变成了图示的效果了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章