我需要启动两个线程,控制哪个线程首先启动,然后让它们交替工作。
以下代码与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')
修改
使用Mike建议的Queue
没有帮助,因为第一个工作人员无需等待第二个工作即可完成工作。
使用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
答案 0 :(得分:2)
解决这个问题的几种方法。一个相对简单的方法是使用锁来控制对单独共享变量的访问:调用另一个变量owner
,它可以设置为A或B.线程A只能在{{1}时启动一个作业}设置为A,线程B只能在owner
设置为B时启动作业。然后伪代码(假设线程A在这里):
owner
B线程只做反转while True:
while True:
# Loop until I'm the owner
lock.acquire()
if owner == A:
break
lock.release()
# Now I'm the owner. And I still hold the lock. Start job.
<Grab next job (or start job or finish job, whatever is required to remove it from contention)>
owner = B
lock.release()
<Finish job if not already done. Go get next one>
和if owner
语句的事情。显然,您可以对其进行参数化,以便两者实际上只运行相同的代码。
修改强>
这是工作版本,在对象中包含建议的逻辑:
owner =
答案 1 :(得分:1)
您可以排除错误的线程获取锁定的可能性,排除依赖time.sleep(...)
的正确性并使用Queue同时缩短您的代码(两个队列用于双向通信):< / p>
import threading
import time
import random
from Queue import Queue
def work_hard(name, i):
print('start %s - %s' % (name, i))
time.sleep(random.uniform(0.2, 1))
print('end %s - %s' % (name, i))
def worker(name, q_mine, q_his):
for i in range(5):
q_mine.get()
work_hard(name, i)
q_his.put(1)
qAB = Queue()
qBA = Queue()
t1 = threading.Thread(target=worker, args=('A', qAB, qBA))
t2 = threading.Thread(target=worker, args=('B', qBA, qAB))
t1.start()
qAB.put(1) # notice how you don't need time.sleep(...) even here
t2.start()
t1.join()
t2.join()
print('done')
它按照您的指定工作。或者,您可以使用threading.Condition
(acquire
,release
,wait
和notify
/ notifyAll
的组合,但这会更加微妙,特别是在哪个线程首先出现。