Python Multi thread
一個簡單的MULTI THREAD
from threading import Thread def add_100(): tmp = 0 for i in range(0,100): tmp += i print tmp def add_2000(): tmp = 0 for i in range(0,2000): tmp += i print tmp threads = [] for func in [add_100, add_2000]: threads.append(Thread(target=func)) threads[-1].start() for thread in threads: thread.join()
試一下LOCK 之 無LOCK
from threading import Lock, Thread import random, time lock = Lock() g = 0 def add_1000(): global g #lock.acquire() for i in range(0,5): time.sleep(random.randrange(2, 5)) g += 1 print str(g) + "\n" #lock.release() def add_2000(): global g #lock.acquire() for i in range(0,5): time.sleep(random.randrange(2, 5)) g += 10 print str(g) + "\n" #lock.release() threads = [] for func in [add_1000, add_2000]: threads.append(Thread(target=func)) threads[-1].start() for thread in threads: thread.join()
結果
1
11
21
22
32
33
43
44
54
55
g 這個參數被兩個thread 同時更動。
試一下LOCK 之 有LOCK
from threading import Lock, Thread import random, time lock = Lock() g = 0 def add_1000(): global g lock.acquire() for i in range(0,5): time.sleep(random.randrange(2, 5)) g += 1 print str(g) + "\n" lock.release() def add_2000(): global g lock.acquire() for i in range(0,5): time.sleep(random.randrange(2, 5)) g += 10 print str(g) + "\n" lock.release() threads = [] for func in [add_1000, add_2000]: threads.append(Thread(target=func)) threads[-1].start() for thread in threads: thread.join()
結果
1
2
3
4
5
15
25
35
45
55
試試看RLock
from threading import Lock, Thread, RLock import random, time lock = RLock() g = 0 def add_1000(): global g for i in range(0,5): lock.acquire() time.sleep(random.randrange(2, 5)) g += 1 print str(g) + "\n"
lock.release()
lock.release()
lock.release()
lock.release()
lock.release() def add_2000(): global g lock.acquire() for i in range(0,5): time.sleep(random.randrange(2, 5)) g += 10 print str(g) + "\n" lock.release() threads = [] for func in [add_1000, add_2000]: threads.append(Thread(target=func)) threads[-1].start() for thread in threads: thread.join()
我們把lock.acquire()放在for回圈中,如果lock=Lock(),第一個回圈就會停住了。
因為Lock()一定需要lock.acquire()配一個lock.release()。
如果把lock = RLock()。lock.acquire()與lock.release()就可以如上例,重覆多次acquire, 再一次全部一起release()。
EVENTS
from threading import Lock, Thread, Event
import random, time
lock = Lock()
e = Event()
g = 0
def add_1000(e):
global g
for i in range(0,5):
g += 1
print str(g) + "\n"
e.wait()
print "yes go"
e.clear()
def add_2000(e):
global g
for i in range(0,5):
g += 10
print str(g) + "\n"
e.set()
threads = []
for func in [add_1000, add_2000]:
threads.append(Thread(target=func, args=(event,)))
threads[-1].start()
for thread in threads:
thread.join()
結果
1
11
21
yes go
31
32
42
yes go
52
53
yes go
54
Event可以讓兩個thread構通, 藉由wait與set,由event.wait()等待另一個thread對event下set。原本wait就會解除。
由上例,可以看出add_2000會不斷送出event.set()讓event.wait()往下走。
本來期待可以出現
1
11
yes go
12
22
yes go
23
33
yes go
34
44
yes go
45
55
可以發現"yes go"只出現三次,因為add_2000送的set是不斷的送出,而add_1000的wait還沒有跑到。Condition
from threading import Lock, Thread, Event,Condition import random, time lock = Lock() e = Event() c = Condition() g = 0 def add_1000(c): global g for i in range(0,5): c.acquire() g += 1 c.wait() g += 1 print "yes go" print str(g) + "\n" c.release() def add_2000(c): global g for i in range(0,5): c.acquire() g += 10 print str(g) + "\n" c.notify() c.release() threads = [] for func in [add_1000, add_2000]: threads.append(Thread(target=func, args=(con,))) threads[-1].start() for thread in threads: thread.join()
結果
11 21 yes go 22 32 43 53 yes go 54
結果差不多,其實condition就是EVENT + LOCK, 以這個角度來說,CONDITON提供的是多個THREAD等待,等到條件成立,就會去使用某些共用的資源。
而EVENT則比較像提供的是多個THREAD等待,等到條件成立,獨立去做某個自的事。
但我們能不能把EVENT寫的很像CONDITION,當然也可以。不就是EVENT+LOCK麼!
留言
張貼留言