Мне нужно запустить два потока, которые управляют первым, а затем чередуя их задания.Как синхронизировать две чередующиеся нити
Следующий код работает так, как ожидается, с do_sleep = True
, но может завершиться с ошибкой do_sleep = False
.
Как я могу достичь такого же результата, не используя эти уродливые (и ненадежные) сна?
Причина, почему она работает с do_sleep = True
что:
- Каждый рабочий поток дает время на другой поток, чтобы начать, прежде чем пытаться получить блокировку и начать следующую работу
- Существует пауза между начало первой и второй рабочий, который позволяет первому один получить блокировку перед второй готов
с do_sleep = False
он может потерпеть неудачу, потому что:
- В конце каждого задания, каждый поток может попытаться получить блокировку для следующего цикла до другого потока, выполнение двух последовательных заданий вместо переменного
- Второго поток может получить блокировку перед первым
Вот код:
import threading
import time
import random
do_sleep = True
def workerA(lock):
for i in range(5):
lock.acquire()
print('Working A - %s' % i)
time.sleep(random.uniform(0.2, 1))
lock.release()
if do_sleep: time.sleep(0.1)
def workerB(lock):
for i in range(5):
if do_sleep: time.sleep(0.1)
lock.acquire()
print('Working B - %s' % i)
time.sleep(random.uniform(0.2, 1))
lock.release()
if do_sleep: time.sleep(0.1)
lock = threading.Lock()
t1 = threading.Thread(target=workerA, args=(lock,))
t2 = threading.Thread(target=workerB, args=(lock,))
t1.start()
if do_sleep: time.sleep(0.1)
t2.start()
t1.join()
t2.join()
print('done')
EDIT Использование Queue
в sugge Майк не помогает, потому что первый рабочий закончил работу, не дожидаясь второго.
Это неправильный выход версии после замены Lock
с Queue
:
Working A - 0
Working A - 1
Working B - 0
Working A - 2
Working B - 1
Working A - 3
Working B - 2
Working A - 4
Working B - 3
Working B - 4
done
Это неправильный выход, полученный с do_sleep = False
:
Working A - 0
Working A - 1
Working A - 2
Working A - 3
Working A - 4
Working B - 0
Working B - 1
Working B - 2
Working B - 3
Working B - 4
done
Это правильный выход, полученные с использованием do_sleep = True
:
Working A - 0
Working B - 0
Working A - 1
Working B - 1
Working A - 2
Working B - 2
Working A - 3
Working B - 3
Working A - 4
Working B - 4
done
в действительности это действительно дубликат: http://stackoverflow.com/questions/16665367/why-doesnt-a-simple-python-producer-consumer-multi-threading-program-speed-up-b –
Нет, я пытался с «Очередью», и он не работает. – stenci