⼀個執行緒寫⼊,⼀個執行緒讀取,沒問題,如果兩個執行緒都寫⼊呢?
import threading
import time
import dis
num=
0def
demo1
(nums)
:global num
for i in
range
(nums)
: num+=
1print
('demo1---%d'
%num)
defdemo2
(nums)
:global num
for i in
range
(nums)
: num +=
1print
('demo2---%d'
% num)
defmain()
: t1=threading.thread(target=demo1,args=
(1000000,)
) t2= threading.thread(target=demo1, args=
(1000000,)
) t1.start(
) t2.start(
)print
('main---%d'
%num)
if __name__==
'__main__'
: main(
)
2.1 互斥鎖
當多個執行緒⼏乎同時修改某⼀個共享資料的時候,需要進⾏同步控制。 某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為"鎖定",其他執行緒 不能改變,只到該執行緒釋放資源,將資源的狀態變成"⾮鎖定",其他的執行緒才能 再次鎖定該資源。
互斥鎖保證了每次只有⼀個執行緒進⾏寫⼊操作,從⽽保證了 多執行緒情況下資料的正確性。
# 建立鎖
mutex = threading.lock(
)#鎖定
mutex.acquire(
)#解鎖
mutex.release(
)
import threading
import time
#import dis
# mutex=threading.lock()
mutex=threading.rlock(
)#可以上多把鎖,但是加鎖和解鎖的數量要一一對應
num=
0def
demo1
(nums)
:global num
mutex.acquire(
) mutex.acquire(
)for i in
range
(nums)
: num +=
1# mutex.release()
mutex.release(
)print
('demo1---%d'
%num)
defdemo2
(nums)
:global num
mutex.acquire(
)for i in
range
(nums)
: num +=
1 mutex.release(
)print
('demo2---%d'
%num)
defmain()
: t1=threading.thread(target=demo1,args=
(1000000,)
) t2=threading.thread(target=demo2,args=
(1000000,)
) t1.start(
) t2.start(
) time.sleep(3)
print
('main---%d'
%num)
if __name__ ==
'__main__'
: main(
)
2.2 死鎖import threading
import time
class
mythread1
(threading.thread)
:def
run(self)
:# 對mutexa上鎖
mutexa.acquire(
)# mutexa上鎖後,延時1秒,等待另外那個執行緒 把mutexb上鎖
print
(self.name+
'----do1---up----'
) time.sleep(1)
# 此時會堵塞,因為這個mutexb已經被另外的執行緒搶先上鎖了
mutexb.acquire(
)print
(self.name+
'----do1---down----'
) mutexb.release(
)# 對mutexa解鎖
mutexa.release(
)class
mythread2
(threading.thread)
:def
run(self)
:# 對mutexb上鎖
mutexb.acquire(
)#mutexb上鎖後,延時1秒,等待另外那個執行緒 把mutexa上鎖
print
(self.name+
'----do2---up----'
) time.sleep(1)
2930
# 此時會堵塞,因為這個mutexa已經被另外的執行緒搶先上鎖了
mutexa.acquire(
)print
(self.name+
'----do2---down----'
) mutexa.release()3
# 對mutexb解鎖
mutexb.release(
) mutexa = threading.lock(
) mutexb = threading.lock(
)if __name__ ==
'__main__'
: t1 = mythread1(
) t2 = mythread2(
) t1.start(
) t2.start(
)
2.3 避免死鎖
程式設計時要盡量避免
新增超時時間等
import threading
# from threading import condition
class
xiaoai
(threading.thread)
:def
__init__
(self,cond)
:# super() 可以用來獲取當前類的父類
super()
.__init__(name=
'小愛'
) self.cond = cond
defrun(self)
:# self.cond.acquire()
# print(4)
with self.cond:
self.cond.wait(
)# print(5)
print
('{}: 在'
.format
(self.name)
) self.cond.notify(
) self.cond.wait(
)print
('{}: 你猜猜幾點了'
.format
(self.name)
) self.cond.notify(
)# self.cond.release()
class
tianmao
(threading.thread)
:def
__init__
(self, cond)
:# super() 可以用來獲取當前類的父類
super()
.__init__(name=
'天貓'
) self.cond = cond
defrun(self)
: self.cond.acquire(
)print
('{}: 小愛同學'
.format
(self.name)
)# print(1)
self.cond.notify(
)# print(2)
self.cond.wait(
)# print(3)
print
('{}: 現在幾點了?'
.format
(self.name)
) self.cond.notify(
) self.cond.release(
)if __name__ ==
'__main__'
:# 定義一把鎖
# mutex = threading.rlock()
cond = threading.condition(
) xiaoai = xiaoai(cond)
tianmao = tianmao(cond)
xiaoai.start(
) tianmao.start(
)
結果
天貓: 小愛同學
小愛: 在
天貓: 現在幾點了?
小愛: 你猜猜幾點了
爬蟲多執行緒
多執行緒在之前的scrapy裡面已經接觸過了,就是裡面的yiled,開啟乙個新的執行緒。但是這是這是基於這個高階框架的,用的時候只知道這是開啟了乙個新的執行緒,並不是很清楚到底是怎麼執行的。而在python裡面有包 import threading引入這個包之後就可以寫自己的多執行緒了 寫多執行緒的...
多執行緒爬蟲
python標準庫是執行緒之間常見的資料交換形式 queue的使用可以確保python的執行緒安全 q queue.queue maxsize 建立佇列,並可以指定大小 q.empty 判斷佇列是否為空 q.full 判斷佇列是否滿 q.put data 向佇列中放入資料 q.get 從佇列中拿資料...
爬蟲多執行緒
執行緒程序 import requests import threading import json from queue import queue import time 寫子類 class thread crawl threading.thread def init self,name,page...