我想知道是否有可能開始一個新的線程,並更新其參數時,這種說法得到主的程序的新值更新參數,所以這樣的事情:的Python:螺紋
i = 0
def foo(i):
print i
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i = i+1
非常感謝您的幫助!
我想知道是否有可能開始一個新的線程,並更新其參數時,這種說法得到主的程序的新值更新參數,所以這樣的事情:的Python:螺紋
i = 0
def foo(i):
print i
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i = i+1
非常感謝您的幫助!
參數只是一個值,就像其他任何東西一樣。傳遞值只是對同一個值進行新的引用,如果您改變該值,則每個引用都會看到它。
全局變量和函數參數具有相同名稱的事實在這裏並不相關,並且有點令人困惑,所以我要重命名其中的一個。另外,您的foo
函數只能在print
一次(甚至可能在您增加值之前),然後休眠5秒鐘,然後結束。你可能想要一個循環,否則,你不能確定事情是否正常工作。
所以,這裏有一個例子:
i = []
def foo(j):
while True:
print j
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i.append(1)
那麼,爲什麼沒有你的代碼的工作?那麼,i = i+1
沒有突變值0
,它將新值值分配給i
。 foo
函數仍舊引用舊值0
,該值保持不變。
由於整數是不變的,所以不能直接解決這個問題。但你可以間接地很容易解決:替換整數與某種包裝是 mutable。
例如,您可以使用set
和get
方法編寫IntegerHolder類;當你i.set(i.get() + 1)
,而另一個參考i.get()
,它會看到新的價值。
或者您可以使用list
作爲持有人。列表是可變的,並保存零個或多個元素。當您執行i[0] = i[0] + 1
時,用一個新的整數值替換i[0]
,但i
仍然是相同的列表值,這就是其他參考指向的內容。所以:
i = [0]
def foo(j):
print j[0]
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i[0] = i[0]+1
這可能看起來有點亂,但它實際上是一個很常見的Python成語。
同時,foo
在另一個線程中運行這一事實會產生另一個問題。
理論上,線程同時運行,並且它們之間沒有任何數據訪問的排序。您的主線程可以在覈心0上運行,並且在覈心0的緩存中處理i
的副本,而foo
線程在覈心1上運行,並在核心1的緩存中處理另一個i
副本,並且存在你的代碼中沒有任何東西強制高速緩存同步。
實際上,您經常會忽略這一點,特別是在CPython中。但實際上,當你知道時,你必須學習Global Interpreter Lock是如何工作的,以及解釋器如何處理變量以及(在某些情況下)如何處理平臺的緩存一致性和C實現的內存模型等工作。所以,你不應該依賴它。正確的做法是使用某種同步機制來防止訪問i
。作爲一個方面說明,你也應該幾乎從不使用thread
而不是threading
,所以我也要切換它。
i = []
lock = threading.Lock()
def foo(j):
while True:
with lock:
print j[0]
time.sleep(5)
t = threading.Thread(target=foo, args=(i,))
t.start()
while True:
with lock:
i[0] = i[0]+1
最後一件事:如果你創建一個線程,你需要join
它以後,也不能清晰地退出。但是你的foo
線程永不退出,所以如果你嘗試join
它,你將永遠阻止。
對於這樣的簡單情況,有一個簡單的解決方案。致電t.start()
之前,請撥打t.daemon = True
。這意味着當你的主線程退出時,後臺線程會在某個任意點自動終止。如果是寫入文件或數據庫,那顯然是一件壞事。但就你而言,它沒有做任何持久或危險的事情。
對於更實際的情況,您通常需要創建某種方式來在兩個線程之間發送信號。通常你已經得到了線程等待的東西 - Queue
,一個文件對象或它們的集合(通過select
)等。如果不是,只需創建一個由鎖(或條件或其他適當的東西)保護的標誌變量)。
非常感謝您對線程工作方式的非常清晰的解釋。它現在更有意義,而且效果很棒!實際上,我的意思是在foo函數中使用while循環。 – Tomas 2013-03-29 12:10:44
嘗試使用全局變量。
i = 0
def foo():
print i
time.sleep(5)
thread.start_new_thread(foo,())
while True:
i = i+1
你也可以傳遞一個哈希來存放你需要的變量。
args = {'i' : 0}
def foo(args):
print args['i']
time.sleep(5)
thread.start_new_thread(foo,(args,))
while True:
args['i'] = arg['i'] + 1
您可能還想使用線程鎖定。
import thread
lock = thread.allocate_lock()
args = {'i' : 0}
def foo(args):
with lock:
print args['i']
time.sleep(5)
thread.start_new_thread(foo,(args,))
while True:
with lock:
args['i'] = arg['i'] + 1
希望這對我有所幫助。
你試過這個嗎?發生了什麼? – 2013-03-27 20:19:30