对于类似于监管项目的工程,我使用线程库来管理一些子进程。在某些时候,用户可以提示命令以向处理管理线程发送指令。这些命令存储在主进程和处理管理线程之间共享的队列对象中。我认为我需要互斥锁来解决并发问题,所以我先写了一个小脚本来尝试它,但首先没有使用互斥锁,以确保我得到预期的并发问题。
我希望从脚本中输出每秒钟混乱的整数列表:
但实际上它会打印出以下整数的漂亮列表,就像这样:
但我得到了相同的结果,有点“慢”:
我想知道在线程之间共享一个类似于队列的对象时,是否真的需要互斥量来管理?另外,从上面的代码中,我该如何有效地重现我正在寻找的并发问题?
感谢阅读。
编辑1: 根据user4815162342的评论,我更改了第一个代码片段,并通过将睡眠调用移动到“较长”函数中的值检索和列表附加之间,成功产生了某种竞态条件。
我希望从脚本中输出每秒钟混乱的整数列表:
import threading
import time
def longer(l, mutex=None):
while 1:
last_val = l[-1]
l.append(last_val + 1)
time.sleep(1)
return
dalist = [0]
t = threading.Thread(target=longer, args=(dalist,))
t.daemon = True
t.start()
while 1:
last_val = dalist[-1]
dalist.append(last_val + 1)
print dalist
time.sleep(1)
但实际上它会打印出以下整数的漂亮列表,就像这样:
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4, 5, 6]
根据另一篇帖子中this的答案,我认为它来自线程库,因此我使用了同样的方法使用了多进程库:
import multiprocessing as mp
import time
def longer(l, mutex=None):
while 1:
last_val = l[-1]
l.append(last_val + 1)
time.sleep(1)
return
dalist = [0]
t = mp.Process(target=longer, args=(dalist,))
t.start()
while 1:
last_val = dalist[-1]
dalist.append(last_val + 1)
print dalist
time.sleep(1)
但我得到了相同的结果,有点“慢”:
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
我想知道在线程之间共享一个类似于队列的对象时,是否真的需要互斥量来管理?另外,从上面的代码中,我该如何有效地重现我正在寻找的并发问题?
感谢阅读。
编辑1: 根据user4815162342的评论,我更改了第一个代码片段,并通过将睡眠调用移动到“较长”函数中的值检索和列表附加之间,成功产生了某种竞态条件。
import threading
import time
def longer(l, mutex=None):
while 1:
last_val = l[-1]
time.sleep(1)
l.append(last_val + 1)
return
dalist = [0]
t = threading.Thread(target=longer, args=(dalist,))
t.daemon = True
t.start()
while 1:
last_val = dalist[-1]
dalist.append(last_val + 1)
print dalist
time.sleep(1)
这给我提供了像这样的东西:
[0, 1]
[0, 1, 1, 2]
[0, 1, 1, 2, 2, 3]
[0, 1, 1, 2, 2, 3, 3, 4]
我成功地使用线程锁来解决了我的人工问题,方法如下:
import threading
import time
def longer(l, mutex=None):
while 1:
if mutex is not None:
mutex.acquire()
last_val = l[-1]
time.sleep(1)
l.append(last_val + 1)
if mutex is not None:
mutex.release()
return
dalist = [0]
mutex = threading.Lock()
t = threading.Thread(target=longer, args=(dalist, mutex))
t.daemon = True
t.start()
while 1:
if mutex is not None:
mutex.acquire()
last_val = dalist[-1]
dalist.append(last_val + 1)
if mutex is not None:
mutex.release()
print dalist
time.sleep(1)
然后生成:
[0, 1, 2]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]