我想知道当这个参数在程序的主程序中获得一个新值时,是否可以启动一个新线程并更新它的参数,所以像这样:
i = 0
def foo(i):
print i
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i = i+1
非常感谢您的帮助!
我想知道当这个参数在程序的主程序中获得一个新值时,是否可以启动一个新线程并更新它的参数,所以像这样:
i = 0
def foo(i):
print i
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i = i+1
非常感谢您的帮助!
参数只是一个值,就像其他任何东西一样。传递该值只会对相同的值进行新的引用,如果您改变该值,每个引用都会看到它。
全局变量和函数参数具有相同名称的事实在这里无关紧要,并且有点令人困惑,因此我将重命名其中一个。此外,您的foo
函数只执行print
一次(可能在您增加值之前),然后休眠 5 秒,然后完成。你可能想要一个循环;否则,您实际上无法判断事情是否正常。
所以,这里有一个例子:
i = []
def foo(j):
while True:
print j
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i.append(1)
那么,为什么您的代码不起作用?好吧,i = i+1
不是改变 value 0
,而是将新值 ,分配0 + 1
给i
。该foo
函数仍然具有对0
未更改的旧值的引用。
由于整数是不可变的,所以不能直接解决这个问题。但是你可以很容易地间接解决它:用某种可变的包装器替换整数。
例如,您可以使用set
和get
方法编写一个 IntegerHolder 类;当您i.set(i.get() + 1)
和其他参考这样做i.get()
时,它将看到新值。
或者您可以只使用 alist
作为支架。列表是可变的,并且包含零个或多个元素。当您这样做时i[0] = i[0] + 1
,它将替换i[0]
为一个新的整数值,但i
仍然是相同的列表值,这就是另一个引用所指向的内容。所以:
i = [0]
def foo(j):
print j[0]
time.sleep(5)
thread.start_new_thread(foo,(i,))
while True:
i[0] = i[0]+1
这可能看起来有点 hacky,但它实际上是一个非常常见的 Python 习惯用法。
同时,在另一个线程中运行的事实foo
产生了另一个问题。
理论上,线程同时运行,它们之间的任何数据访问都没有顺序。您的主线程可能在核心 0 上运行,并处理i
核心 0 缓存中的副本,而您的foo
线程在核心 1 上运行,并处理核心 1 缓存中的不同副本,i
您的强制缓存同步的代码。
在实践中,您通常会侥幸逃脱,尤其是在 CPython 中。但是要真正知道什么时候可以摆脱它,你必须了解全局解释器锁是如何工作的,解释器如何处理变量,(在某些情况下)甚至你的平台的缓存一致性和你的 C 实现的内存模型等等在工作。所以,你不应该依赖它。正确的做法是使用某种同步机制来保护对i
.
作为旁注,您也应该几乎永远不要使用thread
代替threading
,所以我也将切换它。
i = []
lock = threading.Lock()
def foo(j):
while True:
with lock:
print j[0]
time.sleep(5)
t = threading.Thread(target=foo, args=(i,))
t.start()
while True:
with lock:
i[0] = i[0]+1
最后一件事:如果你创建了一个线程,你以后需要join
它,否则你不能干净地退出。但是你的foo
线程永远不会退出,所以如果你尝试join
它,你将永远阻塞。
对于像这样的简单情况,有一个简单的解决方案。在打电话之前t.start()
,做t.daemon = True
。这意味着当您的主线程退出时,后台线程将在某个任意点自动终止。如果是写入文件或数据库,这显然是一件坏事。但在你的情况下,它并没有做任何持久或危险的事情。
对于更实际的情况,您通常希望创建某种方式在两个线程之间发出信号。通常你已经有一些东西让线程等待——a Queue
、文件对象或它们的集合(通过select
)等。如果没有,只需创建一个受锁保护的标志变量(或条件或任何适当的)。
尝试全局变量。
i = 0
def foo():
print i
time.sleep(5)
thread.start_new_thread(foo,())
while True:
i = i+1
您还可以传递包含所需变量的哈希。
args = {'i' : 0}
def foo(args):
print args['i']
time.sleep(5)
thread.start_new_thread(foo,(args,))
while True:
args['i'] = arg['i'] + 1
您可能还想使用线程锁。
import thread
lock = thread.allocate_lock()
args = {'i' : 0}
def foo(args):
with lock:
print args['i']
time.sleep(5)
thread.start_new_thread(foo,(args,))
while True:
with lock:
args['i'] = arg['i'] + 1
希望这有帮助。