(併發編程)進程 (multiprocessing--Process實現進程併發)

['建立進程2方式種',
'進程對象屬性:join方法,守護進程obj.daemon=True,obj.pid, obj.name, obj.terminate(),obj.is_alive()等 '
'os.getpid,os.getppid',
'互斥鎖(Lock())',
'殭屍進程與孤兒進程',
'內存空間物理上隔離']
併發的本質:切換+保持狀態

1、同一個程序執行屢次是多個進程
每個進程有一個PID
import os
os.getppid()   #父的pid (pycharm.exe)#cmd 中 pyhon 路徑 父的pid(cmd.exe)
os.getpid()    #本身的pid (python.exe)
2、開啓子進程的兩種方式
windows (createprocess) 建立子進程時子輩除了拷貝父輩的信息還建立了些本身的東西
unix (fork) 建立子進程時拷貝父輩的信息子進程的初始狀態和父輩一致
第一種(比較經常使用)                                                                                                                                                                                                           
from multiprocessing import Process                                                                                                                                                                                 
import time                                                                                                                                                                                                         
                                                                                                                                                                                                                    
def task(name):                                                                                                                                                                                                     
    print('%s is running' %name)                                                                                                                                                                                    
    time.sleep(3)                                                                                                                                                                                                   
    print('%s is done' %name)                                                                                                                                                                                       
                                                                                                                                                                                                                    
if __name__ == '__main__':                                                                                                                                                                                          
    # 在windows系統之上,開啓子進程的操做必定要放到這下面                                                                                                                                                                                 
    # Process(target=task,kwargs={'name':'egon'})   #兩種傳參方式皆可                                                                                                                                                        
    p=Process(target=task,args=('egon',))          #兩種傳參方式皆可                                                                                                                                                        
    p.start() # 向操做系統發送請求,操做系統會申請內存空間,把父進程的數據拷貝給子進程,做爲子進程的初始狀                                                                                                                          
    print('======主')                                                                                                                                                                                                
                                                                                                                                                                                                                    
第二種                                                                                                                                                                                                                 
from multiprocessing import Process                                                                                                                                                                                 
import time                                                                                                                                                                                                         
                                                                                                                                                                                                                    
class MyProcess(Process):                                                                                                                                                                                           
    def __init__(self,name):                                                                                                                                                                                        
        super(MyProcess,self).__init__()     #Process在init裏面有相應設置,要遺傳下來,不然報錯                                                                                                                                        
        self.name=name                                                                                                                                                                                              
                                                                                                                                                                                                                    
    def run(self):                                                                                                                                                                                                  
        print('%s is running' %self.name)                                                                                                                                                                           
        time.sleep(3)                                                                                                                                                                                               
        print('%s is done' %self.name)                                                                                                                                                                              
                                                                                                                                                                                                                    
if __name__ == '__main__':                                                                                                                                                                                          
    p=MyProcess('egon')                                                                                                                                                                                             
    p.start()   #p.start()調用了類中的run()方法(規定)                                                                                                                                                                         
print('主')
3、進程的內存空間相互隔離
from multiprocessing import Process                    
import time                                            
                                                       
x=1000                                                                                                       
def task():                                            
    time.sleep(3)                                      
    global x                                           
    x=0                                                
    print('兒子死啦',x)                                    
#在以前最好只有函數或變量的定義,沒有具體的執行(print等)                                                       
if __name__ == '__main__':                                                                      
    p=Process(target=task)                             
    p.start()                                          
    time.sleep(5)                                      
print(x)    
#在子進程中對變量x的修改不影響父進程中x的值
4、父進程等待子進程結束 p1.join()
#(等待p1 卡住)等兒子死了,wait回收兒子的pid等遺留下的東西
#瞭解 連續start再連續join 和 連續start,join。。。。
from multiprocessing import Process                                    
import time                                                            
                                                                       
x=1000                                                                                        
def task(n):                                                           
    print('%s is runing' %n)                                           
    time.sleep(n)                                                      
                                                                       
if __name__ == '__main__':                                             
    start_time=time.time()                                             
                                                                       
    p1=Process(target=task,args=(1,))                                  
    p2=Process(target=task,args=(2,))                                  
    p3=Process(target=task,args=(3,))                                  
    p1.start()                                                         
    p2.start()                                                         
    p3.start()                                                         
                                                                       
    p3.join() #3s                                                      
    p1.join()                                                          
    p2.join()                                                      
                                                                       
print('主',(time.time() - start_time))        #3.01637601852417     
#用循環
from multiprocessing import Process                                  
import time                                                          
                                                                     
x=1000                                                               
                                                                     
def task(n):                                                         
    print('%s is runing' %n)                                         
    time.sleep(n)                                                    
                                                                     
if __name__ == '__main__':                                           
    start_time=time.time()                                           
    p_l=[]                                                           
    for i in range(1,4):                                             
        p=Process(target=task,args=(i,))                             
        p_l.append(p)                                                
        p.start()                                                    
                                                                     
    for p in p_l:                                                    
        p.join()                                                     
                                                                     
print('主',(time.time() - start_time))       #3.0141923427581787
5、進程對象的其餘屬性
from multiprocessing import Process                                     
import time                                                             
                                                                        
def task(n):                                                            
    print('%s is runing' %n)                                            
    time.sleep(n)                                                       
                                                                        
if __name__ == '__main__':   # 在windows系統之上,開啓子進程的操做必定要放到這下面                                            
    start_time=time.time()                                              
    p1=Process(target=task,args=(1,),name='任務1') 
    p1 daemon=True    #再obj發出建立前,將obj變成守護進程,主進程執行完畢後子進程跟着結束
    p1.start()         #向操做系統發建立子進程請求,父進程無需等待                                                    
    print(p1.pid)                                                       
    print(p1.name)     #如前面不定義name,默認process-1 etc                      
    p1.terminate()     #向操做系統發請求,父進程無需等待                            
    p1.join()          #等待該子進程結束(卡住吧),父進程須要等待一點時間                                                
    print(p1.is_alive())                                                
    print('主')       #這裏的效果是主進程等兒子死了,再結束
from multiprocessing import Process                         
import time,os                                              
                                                            
def task():                                                 
    print('self:%s parent:%s' %(os.getpid(),os.getppid()))  
    time.sleep(3)                                           
                                                            
if __name__ == '__main__':                                  
    p1=Process(target=task,)                                
    p1.start()                                              
    print(p1.pid)                                           
print('主',os.getpid())  
6、殭屍進程與孤兒進程
在unix系統中init是全部進程的爹;建立進程用fork,回收進程(結束進程的殘留信息?)用waitpid
殭屍進程(有害:佔用pid):子代先於父代終結,其部分信息(pid等)沒有從系統中刪除,須要父代回收。join中含有回收子代信息的功能。
孤兒進程(無害):父代先於子代終結,子代終結後的部分信息由init代收。
from multiprocessing import Process                     
import time,os                                          
                                                        
def task(n):                                            
    print('%s is running' %n)                           
    time.sleep(n)                                       
                                                        
if __name__ == '__main__':       
 1=Process(target=task,args=(1,))                   
    p1.start()                                          
    p1.join()     # join中含有回收子代信息的功能(wait)                                      
    print('======主',os.getpid()) 
 
 
7、守護進程
父進程  代碼運行完(主線程運行代碼),守護進程就結束
from multiprocessing import Process
import time
def task(name):
    print('%s is running' % name)
    time.sleep(3)
if __name__ == '__main__':
    obj = Process(target=task, args=('egon',))
    obj.daemon=True    #將obj變成守護進程,主進程執行完畢後子進程跟着結束
    obj.start()  # 發送信號給操做系統
  print('主')
8、互斥鎖
強調:必須是lock.acquire()一次,而後 lock.release()釋放一次,才能繼續lock.acquire(),不能連續的lock.acquire()。否者程序停在原地。
     搶同一把鎖:生成鎖對象 必須放在if __name__=='__main__': 下面
互斥鎖vs join
大前提:兩者的原理都是同樣,都是將併發變成串行,從而保證有序(在多個程序共享一個資源時,爲保證有序不亂,需將併發變成串行)
場景: 修改公共數據,若是併發會發出數據錯亂,這時就必須串行執行,就要用到互斥鎖
區別一:join是按照人爲指定的順序執行,而互斥鎖是因此進程平等地競爭,誰先搶到誰執行
區別二:互斥鎖可讓一部分代碼串行,而join只能將代碼總體串行(詳見搶票系統)
  理解:首先join確定是一個子進程對象,互斥鎖能夠加在子進程對象代碼任意部位(要釋放額)
     join人爲安排子進程執行順序,互斥鎖是公平競爭。
  
from multiprocessing import Process,Lock
import time,random
mutex=Lock()  #這裏每一個子進程的都會申請一把鎖
print(id(mutex))
def task1(lock):
     lock.acquire()
 #   print('task1:名字是egon')
 #   time.sleep(random.randint(1,3))
 #   print('task1:性別是male')
     time.sleep(random.randint(1,3))      #with mutex: time.sleep(random.randint(1,3))
 #   print('task1:年齡是18')        
     lock.release()
def task2(lock):
    lock.acquire()
    print('task2:名字是alex')
    time.sleep(random.randint(1,3))
    print('task2:性別是male')
    time.sleep(random.randint(1,3))
    print('task2:年齡是78')
    lock.release()
def task3(lock):
    lock.acquire()
    print('task3:名字是lxx')
    time.sleep(random.randint(1,3))
    print('task3:性別是female')
    time.sleep(random.randint(1,3))
    print('task3:年齡是30')
    lock.release()
if __name__ == '__main__':
    p1=Process(target=task1,args=(mutex,))
    p2=Process(target=task2,args=(mutex,))
    p3=Process(target=task3,args=(mutex,))
    p1.start()
    p2.start()
    p3.start()
last、搶票系統
import json
import time
import random
import os
from multiprocessing import Process,Lock
mutex=Lock()  #每一個子進程都會生成  一把鎖對象,沒用到。能夠優化放在下面 __name__裏面
def search():
    time.sleep(random.randint(1,3))
    with open('db.json','r',encoding='utf-8') as f:
        dic=json.load(f)
        print('%s 剩餘票數:%s' %(os.getpid(),dic['count']))
def get():
    with open('db.json','r',encoding='utf-8') as f:
        dic=json.load(f)
    if dic['count'] > 0:
        dic['count']-=1
        time.sleep(random.randint(1,3))
        with open('db.json','w',encoding='utf-8') as f:
            json.dump(dic,f)
        print('%s 購票成功' %os.getpid())
def task(lock):
    search()
    lock.acquire()
    get()
    lock.release()
if __name__ == '__main__':
    for i in range(10):
        p=Process(target=task,args=(mutex,)) #這裏子進程用的都是主進程這一把鎖 id         p.start()
相關文章
相關標籤/搜索