편집 아래 벤치 마크를 추가 할 수 있습니다.
발전기를 자물쇠로 감쌀 수 있습니다. 예를 들어,
import threading
class LockedIterator(object):
def __init__(self, it):
self.lock = threading.Lock()
self.it = it.__iter__()
def __iter__(self): return self
def next(self):
self.lock.acquire()
try:
return self.it.next()
finally:
self.lock.release()
gen = [x*2 for x in [1,2,3,4]]
g2 = LockedIterator(gen)
print list(g2)
잠금 내 시스템에 50ms가 소요 대기열이 350ms 소요됩니다. 대기열은 실제로 대기열이있을 때 유용합니다. 예를 들어 들어오는 HTTP 요청이 있고 작업자 스레드에서 처리하도록 대기열에 넣으려는 경우입니다. (이것은 파이썬 반복자 모델에 맞지 않습니다. 일단 반복자가 아이템을 다 쓰면, 끝난 것입니다.) 실제로 반복자가 있다면, LockedIterator는 스레드 안전성을 높이는 더 빠르고 간단한 방법입니다.
from datetime import datetime
import threading
num_worker_threads = 4
class LockedIterator(object):
def __init__(self, it):
self.lock = threading.Lock()
self.it = it.__iter__()
def __iter__(self): return self
def next(self):
self.lock.acquire()
try:
return self.it.next()
finally:
self.lock.release()
def test_locked(it):
it = LockedIterator(it)
def worker():
try:
for i in it:
pass
except Exception, e:
print e
raise
threads = []
for i in range(num_worker_threads):
t = threading.Thread(target=worker)
threads.append(t)
t.start()
for t in threads:
t.join()
def test_queue(it):
from Queue import Queue
def worker():
try:
while True:
item = q.get()
q.task_done()
except Exception, e:
print e
raise
q = Queue()
for i in range(num_worker_threads):
t = threading.Thread(target=worker)
t.setDaemon(True)
t.start()
t1 = datetime.now()
for item in it:
q.put(item)
q.join()
start_time = datetime.now()
it = [x*2 for x in range(1,10000)]
test_locked(it)
#test_queue(it)
end_time = datetime.now()
took = end_time-start_time
print "took %.01f" % ((took.seconds + took.microseconds/1000000.0)*1000)
확실히 +1합니다. 적용 가능한 경우 스레딩 시스템을 구성하는 훌륭한 방법입니다. (대부분이 시간이며 확실히이 작업입니다). –