Pythonのプロセスの並行プログラミング(並列同時の基本的な概念、CPUスケジューリング、ブロック)

 

ワン:プロセスの概念:(プロセス) 

プロセスは、プログラムが実行されそれはオペレーティングシステムでありリソース割り当ての最小単位

リソースの割り当て割り当てはあるCPU やメモリや他の物理リソース

プロセスIDは、プロセスの一意な識別子であります

二回2つのプロセスを同じプログラムを実行した後

プロセスおよびプロセス間互いに分離データスルーソケット通信

II:並列並行

同時実行CPU と同じ時間は、複数のプログラムを実行して保管しました

パラレル複数のCPU 連続複数のプログラムを実行すると同時に

3:CPUのプロセススケジューリング方法

先着順先着順(最初の最初のサーバーを来る):最初に来、最初の実行

ショート動作優先アルゴリズムの割り当てCPU とよりは最初に短いのカウントを完了します

ラウンドロビンアルゴリズムタイムスライスの各タスクの実行時間その後、他の実装に

多段フィードバックキューアルゴリズム

 

より長い時間、CPU 短いリソースの割り当てリスト上の優先順位

より短い時間、CPU より多くのリソースの割り当て

 

### プロセスの三状態マップ

 

 

(1)レディ(準備完了)状態

唯一の CPUが外部に実行する必要がある他のすべてのリソースがレディ状態と呼ばれる割り当てられています。

(2)実行(実行中)状態

CPUは、プロセスの実装の実行状態と呼ばれるようになりました。

(3)遮断(ブロック)状態

待機を実行することができないため、イベントが発生した場合それがブロックされているCPUは、他の処理を実行する例えば、待ってI / Oの完了INPUT 、アプリケーション・バッファは、そうで満たし、そしてすることができません。

 

 

これら三つの学習コンテンツではと一緒に以下ドープされています

(1)取得プロセスID

子プロセスIDを取得します)(os.getpid使用します

)(os.getppidを使用し   、親プロセスIDを取得します

#例:

インポートOS、時間

#1 取得サブプロセス[現在のプロセス] ID 
RES1 = os.getpid()
 プリント(RES1)
は、親プロセスのIDを取得し 
RES2 = os.getppid()
 プリント(RES2)
Linuxプロセスの利用底部フォークは、プロセスを作成しますが、内部のウィンドウでフォークをサポートしていません。

あなたがエディタ上で実行されている場合は、親プロセスIDがなされていない、子プロセスの数が親プロセスIDは、番号を実行するプロセスエディタですので、二人の息子のプロセスIDは、このプログラムの実行中の数、プログラムの再実行の過程で変更されることがわかりました再起動した子プロセスを開始します。

2 基本的な使い方)プロセス

例:

インポートOS
 からマルチプロセッシングインポートプロセス
 DEF FUNC():
     プリント" 1.子プロセスID >>>%S、%S >>>上記IDを述べ親プロセス"(os.getpid()、os.getppid()))

IF  __name__ == " __main__ " 印刷" 2.子プロセスID >>>%sの、%S >>>親プロセス上記ID "、os.getppid())(os.getpid())
    は、子プロセスを作成し、プロセスオブジェクトを完了するために指定のタスクを.TARGET返し、次にバックの関数である 
    p過程=(目標= FUNC)
    子プロセスコール 
    )(p.startを

結果は:外部関数の親プロセスIDは変更され、関数内で子と親プロセスID番号は同じですが、それぞれの実行は、番号を変更するプロセスであり、各関数内の子プロセスの数が変更されました。

3 )のパラメータを持つ関数
に依存する同時プロセスのCPUのCPU 以降の幹部は、最初の人幹部をに依存しているために、CPUのスケジューリングポリシー#引数なし機能

#例:

マルチプロセッシングインポートプロセス
 インポートOS 

DEF :FUNC()の
     ための I 範囲(1,6 ):
         印刷" 2.子プロセスIDは>>>%S、%S >>>親プロセスは、上記IDに述べた"(os.getpidを( )、os.getppid()))
 IF  __name__ == " __main__ " 印刷" 1.子プロセスID >>>%S、%S >>>親プロセスIDを上記に述べた"(os.getpid()、OS。 getppid()))
    子プロセスを作成し 
    たp-プロセス=(対象= FUNC)
    子プロセスの呼び出し
    )(p.startを

    N = 5
     のための I における範囲(1、N + 1 ):
         印刷" * " * I)

 


子プロセスがスタック領域に必要な時間枠を開く必要性を作成したので、最初の印刷星は、関数func内循環を印刷した後#

スクリーンショットの結果:

 

 

関数のパラメータがあります#

from multiprocessing import Process
import os,time
def func(n):
    for i in range(1,n+1):
        time.sleep(0.5)
        print("2.子进程id>>>%s,父进程id>>>%s" % (os.getpid(), os.getppid()))
if __name__ == "__main__":
    print("1.子进程id>>>%s,父进程id>>>%s" % (os.getpid(), os.getppid()))
    n = 5
    # 创建子进程 返回进程对象 如果有参数用args 关键字参数执行
    # 对应的值是元组,参数塞到元组中,按照次序排列
    p = Process(target=func,args=(n,))
    p.start()

    for i in range(1,n+1):
        time.sleep(0.3)
        print("*" * i)

# 这时候会造成,星星和func里面打印子进程和父进程的语句相互交错
# 因为子进程开辟栈帧空间的时间极短,所有再哪个不在睡眠时间内先运行哪个进程

效果截图:

 

 

4)进程之间的数据彼此是隔离的

#例:

from multiprocessing import Process
count = 99
def func():
    global count
    count +=1
    print("我是子进程,count=",count)

if __name__ == "__main__":
    p = Process(target=func)
    p.start()
    print("我是主进程,count=",count)

结果输出为:
我是主进程,count= 99
我是子进程,count= 100

5)多个进程的并发

#例:

# 在程序并发时, 因为cpu的调度策略问题,不一定谁先执行,谁后执行
from multiprocessing import Process
import os
def func(args):
    print("args=%s,子进程id号>>>%s, 父进程id号>>>%s" % (args, os.getpid(), os.getppid()))

if __name__ == "__main__":
    for i in range(10):
        Process(target=func, args=(i,)).start()

运行得到结果如下图:

 

 

可以看出父进程id号是不变的,子进程id号是变化的,而且子进程开启不是按顺序的是并发的。

(6)子进程和父进程之间的关系
通常情况下,父进程会比子进程速度稍快,但是不绝对
在父进程执行所有代码完毕之后,会默认等待所有子进程执行完毕
然后在彻底的终止程序,为了方便进程的管理
如果不等待,子进程会变成僵尸进程,在后台不停地占用内存和cpu资源
但是本身由于进程太多,并不容易发现
#例:

from multiprocessing import Process
import os,time
def func(args):
    print("args=%s,子进程id号>>>%s,父进程id号>>>%s" % (args, os.getpid(), os.getppid()))
    time.sleep(1)
    print("args= %s, end" % (args))

if __name__ == "__main__":
    for i in range(10):
        Process(target=func,args=(i,)).start()
        """
        Process(target=func,args=(i,)).start()
        Process(target=func,args=(i,)).start()
        Process(target=func,args=(i,)).start()
        Process(target=func,args=(i,)).start()
        Process(target=func,args=(i,)).start()
        Process(target=func,args=(i,)).start()
        ....
        """
    print("*******父进程*******")

运行后的结果为:

 

 

可以看出父进程号是不变的,子进程是并发的,父进程的执行语句是最快结束的,因为开启子进程需要时间,而主进程的输出没有阻塞所以最快,从print("args= %s, end" % (args))可以知道,子进程是并发的,因为sleep(1)后,如果是顺序执行的话,输出结果不是这样。

四:同步 异步 / 阻塞 非阻塞

场景在多任务当中

同步:必须等我这件事干完了,你在干,只有一条主线,就是同步

异步:没等我这件事情干完,你就在干了,有两条主线,就是异步

阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行

非阻塞:没有任何等待,正常代码往下执行.

 

# 同步阻塞  :效率低,cpu利用不充分

# 异步阻塞  :比如socketserver,可以同时连接多个,但是彼此都有recv

# 同步非阻塞:没有类似input的代码,从上到下执行.默认的正常情况代码

# 异步非阻塞:效率是最高的,cpu过度充分,过度发热

 

1join阻塞基本用法

#例:

from multiprocessing import Process
def func():
    print("我发送第一封邮件....")

if __name__ == "__main__":
    p = Process(target=func)
    p.start()
    # 等待p对象的这个子进程执行完毕之后,在向下执行代码
    # join实际上是加了阻塞
    p.join()  #如果没有join,往往主进程先运行,因为子进程需要开辟栈帧空间相当于加了阻塞
    print("发送第十封邮件")

输出结果为:

我发送第一封邮件....

发送第十封邮件

 

#程序在发送第十封邮件前加了阻塞,是的会先运行子进程结束在运行join之后的语句

(2) 多个子进程通过join 加阻塞,进行同步的控制

例:

from multiprocessing import Process
import time
def func(index):
    time.sleep(0.3)
    print("第%s封邮件已经发送..." % (index))

if __name__ == "__main__":
    lst = []
    for i in range(1,10):
        p = Process(target=func,args=(i,))
        p.start()
        lst.append(p)

    # 把列表里面的每一个进程对象去执行join()
    # 必须等我子进程执行完毕之后了,再向下执行,控制父子进程的同步性
    for i in lst:
        i.join()
    # 等前9个邮件发送之后了,再发第十个
    print("发送第十封邮件")

所以输出结果为:

3封邮件已经发送...

2封邮件已经发送...

1封邮件已经发送...

5封邮件已经发送...

9封邮件已经发送...

6封邮件已经发送...

4封邮件已经发送...

7封邮件已经发送...

8封邮件已经发送...

发送第十封邮件

十个子进程是并发的,所以不一定谁先执行结束,所以不是顺序的。

3)使用类的方法创建子进程

# (1) 基本语法
可以使用自定义的方式创建子进程,
但是必须继承父类Processs
而且所有的逻辑都必须写在run方法里面
#例:

from multiprocessing import Process
import os
class MyProcess(Process):
    # 必须使用叫做run的方法,而且()里面只能是self
    def run(self):
        # 写自定义的逻辑
        print("子进程id>>>%s, 父进程的id>>>%s" % (os.getpid(), os.getppid()))

if __name__ == "__main__":
    p = MyProcess()
    p.start()
    print("主进程:{}".format(os.getpid()))

输出结果为:

主进程:8236

子进程id>>>6412, 父进程的id>>>8236

# (2) 带参数的子进程函数
#例:

from multiprocessing import Process
import os
class MyProcess(Process):

    def __init__(self,arg):
        # 必须调用一下父类的初始化构造方法
        super().__init__()
        self.arg = arg

    # 必须使用叫做run的方法
    def run(self):
        # 在这里就得获取参数
        print("子进程id>>>%s,父进程的id>>>%s" % (os.getpid(),os.getppid()))
        print(self.arg)

if __name__ == "__main__":
    lst = []
    for i in range(1,10):
        p = MyProcess("参数:%s" % (i))
        p.start()
        lst.append(p)

    for i in lst:
        i.join()

    print("最后执行主进程的这句话...",os.getpid())

运行结果为:

子进程id>>>5964,父进程的id>>>5336

参数:2

子进程id>>>10544,父进程的id>>>5336

参数:3

子进程id>>>11512,父进程的id>>>5336

参数:4

子进程id>>>11160,父进程的id>>>5336

参数:5

子进程id>>>12068,父进程的id>>>5336

参数:1

子进程id>>>5288,父进程的id>>>5336

参数:6

子进程id>>>11380,父进程的id>>>5336

参数:8

子进程id>>>8092,父进程的id>>>5336

参数:7

子进程id>>>7120,父进程的id>>>5336

参数:9

最后执行主进程的这句话... 5336

结果分析:父进程是程序运行的主进程号不变,子进程是并发的所以那个参数先打印是不固定的,然后对每个子进程添加了join阻塞,所以没有全部执行完子进程之前,主进程的运行语句是不打印的,也就是在子进程join后主进程运行语句必须等待子进程全部结束才打印。

 

おすすめ

転載: www.cnblogs.com/hszstudypy/p/10992795.html