A. 這個python伺服器為什麼會觸發超時,死鎖還是阻塞怎麼解決
死鎖示例
搞多線程的經常會遇到死鎖的問題,學習操作系統的時候會講到死鎖相關的東西,我們用Python直觀的演示一下。
死鎖的一個原因是互斥鎖。假設銀行系統中,用戶a試圖轉賬100塊給用戶b,與此同時用戶b試圖轉賬200塊給用戶a,則可能產生死鎖。
2個線程互相等待對方的鎖,互相佔用著資源不釋放。
#coding=utf-8
importtime
importthreading
classAccount:
def__init__(self,_id,balance,lock):
self.id=_id
self.balance=balance
self.lock=lock
defwithdraw(self,amount):
self.balance-=amount
defdeposit(self,amount):
self.balance+=amount
deftransfer(_from,to,amount):
if_from.lock.acquire():#鎖住自己的賬戶
_from.withdraw(amount)
time.sleep(1)#讓交易時間變長,2個交易線程時間上重疊,有足夠時間來產生死鎖
print'waitforlock...'
ifto.lock.acquire():#鎖住對方的賬戶
to.deposit(amount)
to.lock.release()
_from.lock.release()
print'finish...'
a=Account('a',1000,threading.Lock())
b=Account('b',1000,threading.Lock())
threading.Thread(target=transfer,args=(a,b,100)).start()
threading.Thread(target=transfer,args=(b,a,200)).start()
防止死鎖的加鎖機制
問題:
你正在寫一個多線程程序,其中線程需要一次獲取多個鎖,此時如何避免死鎖問題。
解決方案:
在多線程程序中,死鎖問題很大一部分是由於線程同時獲取多個鎖造成的。舉個例子:一個線程獲取了第一個鎖,然後在獲取第二個鎖的 時候發生阻塞,那麼這個線程就可能阻塞其他線程的執行,從而導致整個程序假死。 解決死鎖問題的一種方案是為程序中的每一個鎖分配一個唯一的id,然後只允許按照升序規則來使用多個鎖,這個規則使用上下文管理器 是非常容易實現的,示例如下:
importthreading
#Thread-
_local=threading.local()
@contextmanager
defacquire(*locks):
#Sortlocksbyobjectidentifier
locks=sorted(locks,key=lambdax:id(x))
#
acquired=getattr(_local,'acquired',[])
ifacquiredandmax(id(lock)forlockinacquired)>=id(locks[0]):
raiseRuntimeError('LockOrderViolation')
#Acquireallofthelocks
acquired.extend(locks)
_local.acquired=acquired
try:
forlockinlocks:
lock.acquire()
yield
finally:
#
forlockinreversed(locks):
lock.release()
delacquired[-len(locks):]
B. 求助python多線程,執行到100多個停止了
python 線程 暫停, 恢復, 退出
我們都知道python中可以是threading模塊實現多線程, 但是模塊並沒有提供暫停, 恢復和停止線程的方法, 一旦線程對象調用start方法後, 只能等到對應的方法函數運行完畢. 也就是說一旦start後, 線程就屬於失控狀態. 不過, 我們可以自己實現這些. 一般的方法就是循環地判斷一個標志位, 一旦標志位到達到預定的值, 就退出循環. 這樣就能做到退出線程了. 但暫停和恢復線程就有點難了, 我一直也不清除有什麼好的方法, 直到我看到threading中Event對象的wait方法的描述時.
wait([timeout])
Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls set() to set the flag to true, or until the optional timeout occurs.
阻塞, 直到內部的標志位為True時. 如果在內部的標志位在進入時為True時, 立即返回. 否則, 阻塞直到其他線程調用set()方法將標准位設為True, 或者到達了可選的timeout時間.
When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof).
This method returns the internal flag on exit, so it will always return True except if a timeout is given and the operation times out.
當給定了timeout參數且不為None, 它應該是一個浮點數,以秒為單位指定操作的超時(或是分數)。
此方法在退出時返回內部標志,因此除非給定了超時且操作超時,否則它將始終返回True。
Changed in version 2.7: Previously, the method always returned None.
2.7版本以前, 這個方法總會返回None.
<br>
利用wait的阻塞機制, 就能夠實現暫停和恢復了, 再配合循環判斷標識位, 就能實現退出了, 下面是代碼示例:
#!/usr/bin/env python
# coding: utf-8
import threading
import time
class Job(threading.Thread):
def __init__(self, *args, **kwargs):
super(Job, self).__init__(*args, **kwargs)
self.__flag = threading.Event() # 用於暫停線程的標識
self.__flag.set() # 設置為True
self.__running = threading.Event() # 用於停止線程的標識
self.__running.set() # 將running設置為True
def run(self):
while self.__running.isSet():
self.__flag.wait() # 為True時立即返回, 為False時阻塞直到內部的標識位為True後返回
print time.time()
time.sleep(1)
def pause(self):
self.__flag.clear() # 設置為False, 讓線程阻塞
def resume(self):
self.__flag.set() # 設置為True, 讓線程停止阻塞
def stop(self):
self.__flag.set() # 將線程從暫停狀態恢復, 如何已經暫停的話
self.__running.clear() # 設置為False
下面是測試代碼:
a = Job()
a.start()
time.sleep(3)
a.pause()
time.sleep(3)
a.resume()
time.sleep(3)
a.pause()
time.sleep(2)
a.stop()
<br>
測試的結果:
這完成了暫停, 恢復和停止的功能. 但是這里有一個缺點: 無論是暫停還是停止, 都不是瞬時的, 必須等待run函數內部的運行到達標志位判斷時才有效. 也就是說操作會滯後一次.
但是這有時也不一定是壞事. 如果run函數中涉及了文件操作或資料庫操作等, 完整地運行一次後再退出, 反而能夠執行剩餘的資源釋放操作的代碼(例如各種close). 不會出現程序的文件操作符超出上限, 資料庫連接未釋放等尷尬的情況.
C. python多線程中每個線程如果不加休眠時間就會只泡在一個線程上,這該如何處理謝謝
這是三個線程都在跑啊,只是並發的而已
D. python多線程運行過程中出現奇怪的等待行為
你這個程序問題在new = Thread( self.subfunc(i) ) 傳進去的時候就已經調用了self.subfunc
改成 new = Thread( target=self.subfunc, args=(i,) )
另外i 數字太小也看不出來,因為工作量太小,在線程的一個時間片內函數就執行完了,看不到切換的過程,設成if i>10000就明顯了
E. python多線程為什麼會暫停一下,再接著跑 跑一段時間,會暫停幾秒鍾,然後接著列印。
線程之間的輸出,需要在池中中轉,死循環的時間長了,出現滿棧的概率提高,外在表現就是卡一會兒
F. python3.7多線程代碼不執行
使用多進程代替多線程
G. python 程序假死的問題
我遇到的這種現象常見在引用佔用了大量的系統內存,
後來我將直接讀入大量數據到內存的過程改為用iter讀取, 現象沒再出現.
你的方案"超過一定時間...", 可以視為"守護進程",
如果這個進程是你的應用內的某個線程, 恐怕它會一同"睡"去 :(
.. 還是先確認一下是否是內存佔用的原因吧, 如果是通過節省內存的方式可以克服的.
H. python爬蟲多線程假死怎麼解決
如果是爬蟲的話,這個一般都是由於網路原因造成的卡住,可以做兩層控制:
在HTTP請求上設置好超時時間,最好設定sockect的超時,這樣更底層一些。
在上層做一個檢測機制,定時輪詢線程是否正常,如果遇到不響應的直接kill掉。