python3第十天

來源:互聯網
上載者:User

標籤:run   多次   活躍   mon   UI   修改   add   name   .text   

線程:一套流水線的運行過程,作業系統是個工廠,裡面有有多個車間(進程),線程就是每個車間生產的流水線,每個進程,預設都會有個線程進程是資源單元,線程是cpu上的調度單位線程的建立開銷小,共用空間進程直接是競爭關係,線程之間是協作關係  一、線程的模組threading模組方式一from threading import Threadfrom multiprocessing import Process def task():    print(‘is running‘) if __name__ == ‘__main__‘:    t=Thread(target=task,)#線程    # t=Process(target=task,)#進程    t.start()    print(‘主’) 線程的結果:is running主 進程:主is running進程開銷大線程開銷小 方式二from threading import Threadfrom multiprocessing import Processclass MyThread(Thread):    def __init__(self,name):        super().__init__()        self.name=name    def run(self):        print(‘%s is running‘ %self.name) if __name__ == ‘__main__‘:    t=MyThread(‘egon‘)    # t=Process(target=task,)    t.start()    print(‘主’)  二、pid:多線程的pid是一樣的多進程 pid不一樣 三、多線程共用同一個進程內的資源:from threading import Threadfrom multiprocessing import Processn=100def work():    global n    n=0 if __name__ == ‘__main__‘:     # p=Process(target=work,)    # p.start()    # p.join()    # print(‘主‘,n)     t=Thread(target=work,)    t.start()    t.join()    print(‘主‘,n)線程的n會變,進程不會。因為線程共用資源,進程不是,而且進程pid不一樣。  四、多線程共用同一進程記憶體位址空間:from threading import Threadmsg_l=[]format_l=[]def talk():    while True:        msg=input(‘>>: ‘).strip()        msg_l.append(msg) def format():    while True:        if msg_l:            data=msg_l.pop()            format_l.append(data.upper()) def save():    while True:        if format_l:            data=format_l.pop()            with open(‘db.txt‘,‘a‘) as f:                f.write(‘%s\n‘ %data) if __name__ == ‘__main__‘:    t1=Thread(target=talk)    t2=Thread(target=format)    t3=Thread(target=save)     t1.start()    t2.start()    t3.start()  Threading其他方法:#current_thread:當前的線程對象from threading import Thread,activeCount,enumerate,current_threadimport timedef task():    print(‘%s is running‘ %current_thread().getName())    time.sleep(2) if __name__ == ‘__main__‘:    t=Thread(target=task,)    t.start()    t.join()#等待task運行結束(系統回收完)    print(t.is_alive())#返回線程是否活動    print(t.getName())#返回線程名    print(enumerate())#當前活躍的進程對象    print(‘主‘)    print(activeCount())#活著的線程數 主線程從執行層面上代表了,其所在進程的執行過程。  五、守護線程無論是進程還是線程,都遵循:守護會等待主運行完畢後被銷毀需要強調的是:運行完畢並非終止運行from threading import Threadimport time def task1():    print(‘123‘)    time.sleep(10)    print(‘123done‘) def task2():    print(‘456‘)    time.sleep(1)    print(‘456done‘) if __name__ == ‘__main__‘:    t1=Thread(target=task1)    t2=Thread(target=task2)    t1.daemon=True    t1.start()    t2.start()    print(‘主’) 六、GIL

三個需要注意的點:
1.線程搶的是GIL鎖,GIL鎖相當於執行許可權,拿到執行許可權後才能拿到互斥鎖Lock,其他線程也可以搶到GIL,但如果發現Lock仍然沒有被釋放則阻塞,即便是拿到執行許可權GIL也要立刻交出來

2.join是等待所有,即整體串列,而鎖只是鎖住修改共用資料的部分,即部分串列,要想保證資料安全的根本原理在於讓並發變成串列,join與互斥鎖都可以實現,毫無疑問,互斥鎖的部分串列效率要更高

線程1搶到GIL鎖,拿到執行許可權,開始執行,然後加了一把Lock,還沒有執行完畢,即線程1還未釋放Lock,有可能線程2搶到GIL鎖,開始執行,執行過程中發現Lock還沒有被線程1釋放,於是線程2進入阻塞,被奪走執行許可權,有可能線程1拿到GIL,然後正常執行到釋放Lock。。。這就導致了串列啟動並執行效果

七、互斥鎖
from threading import Thread,Lock
import time
n=100
def work():
time.sleep(0.05)
global n
mutex.acquire()
temp=n
time.sleep(0.1)
n=temp-1
mutex.release()

if __name__ == ‘__main__‘:
mutex=Lock()
l=[]
start=time.time()
for i in range(100):
t=Thread(target=work)
l.append(t)
t.start()

for t in l:
t.join()
print(‘run time:%s value:%s‘ %(time.time()-start,n))


#多進程:
#優點:可以利用多核優勢
#缺點:開銷大


#多線程:
#優點:開銷小
#缺點:不能利用多核優勢

# from threading import Thread
# from multiprocessing import Process
# import time
# #計算密集型
# def work():
# res=1
# for i in range(100000000):
# res+=i
#
# if __name__ == ‘__main__‘:
# p_l=[]
# start=time.time()
# for i in range(4):
# # p=Process(target=work) #6.7473859786987305
# p=Thread(target=work) #24.466399431228638
# p_l.append(p)
# p.start()
# for p in p_l:
# p.join()
#
# print(time.time()-start)


from threading import Thread
from multiprocessing import Process
import time
#IO密集型
def work():
time.sleep(2)

if __name__ == ‘__main__‘:
p_l=[]
start=time.time()
for i in range(400):
# p=Process(target=work) #12.104692220687866
p=Thread(target=work) #2.038116455078125
p_l.append(p)
p.start()
for p in p_l:
p.join()

print(time.time()-start)

八、死結與遞迴鎖所謂死結: 是指兩個或兩個以上的進程或線程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死結狀態或系統產生了死結,這些永遠在互相等待的進程稱為死結進程,如下就是死結
死結現象
from threading import Thread,Lock,RLock
import time
mutexA=Lock()
mutexB=Lock()
class Mythread(Thread):
def run(self):
self.f1()
self.f2()

def f1(self):
mutexA.acquire()
print(‘\033[45m%s 搶到A鎖\033[0m‘ %self.name)
mutexB.acquire()
print(‘\033[44m%s 搶到B鎖\033[0m‘ %self.name)
mutexB.release()
mutexA.release()

def f2(self):
mutexB.acquire()
print(‘\033[44m%s 搶到B鎖\033[0m‘ %self.name)
time.sleep(1)
mutexA.acquire()
print(‘\033[45m%s 搶到A鎖\033[0m‘ %self.name)
mutexA.release()
mutexB.release()


if __name__ == ‘__main__‘:
for i in range(20):
t=Mythread()
t.start()

遞迴鎖,在Python中為了支援在同一線程中多次請求同一資源,python提供了可重新進入鎖RLock。

這個RLock內部維護著一個Lock和一個counter變數,counter記錄了acquire的次數,從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。上面的例子如果使用RLock代替Lock,則不會發生死結

#遞迴鎖
from threading import Thread,Lock,RLock
import time
mutex=RLock()
class Mythread(Thread):
def run(self):
self.f1()
self.f2()

def f1(self):
mutex.acquire()
print(‘\033[45m%s 搶到A鎖\033[0m‘ %self.name)
mutex.acquire()
print(‘\033[44m%s 搶到B鎖\033[0m‘ %self.name)
mutex.release()
mutex.release()

def f2(self):
mutex.acquire()
print(‘\033[44m%s 搶到B鎖\033[0m‘ %self.name)
time.sleep(1)
mutex.acquire()
print(‘\033[45m%s 搶到A鎖\033[0m‘ %self.name)
mutex.release()
mutex.release()


if __name__ == ‘__main__‘:
for i in range(20):
t=Mythread()
t.start()
 九、訊號量
from threading import Thread,current_thread,Semaphore
import time,random

sm=Semaphore(5)
def work():
sm.acquire()
print(‘%s 上廁所‘ %current_thread().getName())
time.sleep(random.randint(1,3))
sm.release()

if __name__ == ‘__main__‘:
for i in range(20):
t=Thread(target=work)
t.start()

十、進程池,線程池
進程池
import requests #pip3 install requests
import os,time
from multiprocessing import Pool
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
def get_page(url):
print(‘<%s> get :%s‘ %(os.getpid(),url))
respone = requests.get(url)
if respone.status_code == 200:
return {‘url‘:url,‘text‘:respone.text}

def parse_page(obj):
dic=obj.result()
print(‘<%s> parse :%s‘ %(os.getpid(),dic[‘url‘]))
time.sleep(0.5)
res=‘url:%s size:%s\n‘ %(dic[‘url‘],len(dic[‘text‘])) #類比解析網頁內容
with open(‘db.txt‘,‘a‘) as f:
f.write(res)


if __name__ == ‘__main__‘:

# p=Pool(4)
p=ProcessPoolExecutor()
urls = [
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
]


for url in urls:
# p.apply_async(get_page,args=(url,),callback=parse_page)
p.submit(get_page,url).add_done_callback(parse_page)

p.shutdown()
print(‘主進程pid:‘,os.getpid())


線程池
import requests #pip3 install requests
import os,time,threading
from multiprocessing import Pool
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
def get_page(url):
print(‘<%s> get :%s‘ %(threading.current_thread().getName(),url))
respone = requests.get(url)
if respone.status_code == 200:
return {‘url‘:url,‘text‘:respone.text}

def parse_page(obj):
dic=obj.result()
print(‘<%s> parse :%s‘ %(threading.current_thread().getName(),dic[‘url‘]))
time.sleep(0.5)
res=‘url:%s size:%s\n‘ %(dic[‘url‘],len(dic[‘text‘])) #類比解析網頁內容
with open(‘db.txt‘,‘a‘) as f:
f.write(res)


if __name__ == ‘__main__‘:

# p=Pool(4)
p=ThreadPoolExecutor(3)
urls = [
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
‘http://www.baidu.com‘,
]


for url in urls:
# p.apply_async(get_page,args=(url,),callback=parse_page)
p.submit(get_page,url).add_done_callback(parse_page)

p.shutdown()
print(‘主進程pid:‘,os.getpid())
 

python3第十天

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.