今天學了進程線程一些知識:
自我總結。
1.進程:在爲引入線程之前,是資源調度分配的基本單位(從操作系統中得來)
2.線程:是cpu調度分配資源的基本單位
特點:進程之間是互相不影響的,不能訪問彼此的資源,其中一個進程裏面有多個線程,線程之間可以互相訪問彼此的資源,切有一個父線程和多個子線程。
說說線程:
線程的基本調用方式要會使用,
其中有一個join()方法等同於wait()方法,是指該線程運行完了纔會繼續下面的操作。
而我們的創建守護線程的方法t.setDaemon()=True,必須是在線程開始運行之前設置,他在主線程結束後自動結束.
mutex互斥鎖,遞歸鎖的一些介紹
信號量的引用:
是相當於給定一定空間資源給線程,讓他們最多能同時運行n個,
import threading,time
def run(n):
semp.acquire()#申明一個信號量
time.sleep(2)
print('run the thread %s\n'%n)
semp.release()#釋放一個信號量
if __name__ == '__main__':
semp=threading.BoundedSemaphore(5)#創建5個信號量
for i in range(20):
t=threading.Thread(target=run,args=(i,))
t.start()
while threading.active_count()!=1:
pass
else:
print('the thread done!')
event事件:
創建一個Event對象,然後他會有兩中狀態,set(),clear(),設置和清除設置。
我個人是這樣理解的:類似於操作系統中的阻塞,就緒,和執行,此處跟着做了一個交通燈小實驗
#創建一個event事件,wait()函數相當等待事件set(),否則不運行,當我們使用set()函數之後
#可以使用clear()清除設置,有點類似於阻塞,等待,和執行
#在這裏我們創建一個小汽車等紅綠燈模型
import threading,time
et=threading.Event()
#紅綠燈進程
def light():
count=1 #計算時間的變量
et.set()#初始設置
while True:
if count<6:
print('\033[42;1m the green light!\033[0m')
elif count>=6 and count<=10:
et.clear()
print('\033[41;1m the red light!\033[0m')
else:
et.set()
count=1#時間重置
time.sleep(1)
count+=1
lg=threading.Thread(target=light)
lg.start()
#創建一個車的進程
def car(name):
while True:
if et.is_set():#判斷事件是否被設置
print('%s is running now!!!'%name)
time.sleep(1)
else:
print('%s is stop now!!!'%name)
et.wait()#若紅燈結束,事件被設置在這一直等待
print('\033[32;1m green light is start! gogogo\033[0m')
ca=threading.Thread(target=car,args=('Tasla',))
ca.start()
結果如下:
在後面就是使用隊列簡述簡單的消費者生產者問題:
我們這裏引入的隊列是可以稱爲線程隊列(我自己的看法和總結)
# -*- coding: utf-8 -*-
#Author :The Y Devil
#創建一個隊列來模擬緩衝池
#生產者與消費者共同使用進程來併發執行
import threading,time,queue
q=queue.Queue()
def Producer(name):
count=1
while True:
q.put("第%s骨頭"%count)#把東西放入隊列
print('%s 生成了%s個骨頭\n'%(name,count))
count+=1
time.sleep(0.4)
def Customer(name):
while True:
print('%s 取到了 %s ,並喫掉了他\n'%(name,q.get()))#當get沒有或得值時候會繼續等待,
time.sleep(1)
p=threading.Thread(target=Producer,args=('付,))
p.start()
c=threading.Thread(target=Customer,args=('梁偉',))
c.start()
c1=threading.Thread(target=Customer,args=('皮皮蝦',))
c1.start()
以上大致是今天學習的線程總結
進程
進程可以創建子進程:
子進程除了與父進程代碼共享外,其他都爲繼承父進程的資源,所以彼此也是分開的互不影響的兩個進程
在此獲取不同進程號代碼
print('當前進程名',__name__)
print("父進程號%s"%os.getppid())
print("進程名",os.getpid())
在此處主要想讓自己注意的是進程的隊列,我們之前引導的隊列直接是
import queue
但是對於進程來說,資源互不分享,所以不回獲取到線程隊列,
所以我們需專門引入進程隊列
from multiprocessing import Queue
此處有個例子
# -*- coding: utf-8 -*-
#Author :The Y Devil
#在之前的線程當然,隊列queue可以互相訪問,但是在我們的進程中每個模塊都是獨立的,不能互相訪問
#所有要從進程模塊中導入Queue
from multiprocessing import Process,Queue
import queue
#q=queue.Queue()此方法會報錯,屬於線程的隊列
def n(q):
q.put('123')
if __name__ == '__main__':
q=Queue()#沒有共享一個q隊列,只是相當於克隆了一個q
x=Process(target=n,args=(q,))
x.start()
print(q.get())
兩個進程管道通信:
# -*- coding: utf-8 -*-
#Author :The Y Devil
from multiprocessing import Process,Pipe
#創建一個函數,兩個進程直接數據傳遞--管道
def talk(con):
con.send(['1',2,'i'])#兩個管道互相通信,一個發送即另外個接收,相當於一次一次對接
print(con.recv())
con.close()
if __name__ == '__main__':
parent_con,child_con=Pipe()
parent_con.send('我在這')
t=Process(target=talk,args=(child_con,))
t.start()
print(parent_con.recv())
只可以同時定義兩個管道,可以互相接收和發送消息,若接收時沒有消息則會一直等待
如何實現數據的共享呢?
我們在multiprocessing中有一個Manage()模塊,可以創建可共享的一些數據類型。
如:list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array
那我們來一起看看`
# -*- coding: utf-8 -*-
#Author :The Y Devil
from multiprocessing import Process,Manager
import os
def sa(d,l):
d[os.getpid()]=os.getpid()#把自己的pid號設置成字典
l.append(os.getpid())
#print(d)
print(l)
if __name__ == '__main__':
with Manager() as manage:#和打開文件方式有點相似
d=manage.dict( )
#d={}
l=manage.list(range(4))
p_list=[]
for i in range(10):
m=Process(target=sa,args=(d,l))
m.start()
p_list.append(m)
for res in p_list:
res.join()
print(d)
print(l)
結果:
再此處,測試一下,把manage.dict()換成普通的dict來看看結果。並在父進程和子進程內都打印,在這裏屏蔽了列表的打印
每一個進程都字典都不一樣,說明數據未被共享,