Python 线程锁与强制计时器延迟
Python thread locks vs forced timer delays
据我了解,当您在 Python 中实现全局锁时,这应该为激活锁的线程保留 stdout,因此在线程释放锁之前阻止其他线程使用 stdout。
这是否意味着在下面的代码中,线程 "a" 中的循环应该在线程 "b" 中的函数输出任何内容之前完成?当我 运行 它时,线程 "c" 打印的“7”有时会在 "a".
的输出中交错
我希望输出始终如下所示:
5
5
5
5
5
6
7
但我得到:
5
7
5
5
5
6
代码:
import threading, time
thelock = threading.Lock()
def afunc(var):
with thelock:
for i in range(5):
time.sleep(.0002)
print(var)
def bfunc(var):
print(var)
a=threading.Thread(target=afunc, args=(5,))
b=threading.Thread(target=bfunc, args=(6,))
c=threading.Thread(target=bfunc, args=(7,))
a.start()
b.start()
c.start()
这是 Python 3.4.3 在 OS X 10.10.3 中。当 运行 直接在 OS X 终端或 PyCharm 4.5.1.
中直接打开文件时,会发生相同的行为
你没有实现全局锁,因为没有这样的东西。我的意思是,有但那是 Global Interpreter Lock,它是一种语言功能,而您没有实现它。
吉尔:
http://en.wikipedia.org/wiki/Global_Interpreter_Lock
现在,关于您正在实施的锁:
threading.Lock() -
returns 一个新的 原始 锁定对象的工厂函数。一旦一个线程获取它,随后尝试获取它阻塞,直到它被释放;任何线程都可以释放它。
查看线程的官方文档:https://docs.python.org/2/library/threading.html
一般来说,当您将某些资源锁定到临界区时,该资源将仅被锁定,线程也必须获得锁才能访问共享资源。在您的示例中,函数 b 在写入标准输出之前不会尝试获取锁。
此外,我相当确定这不会像您预期的那样工作,并且输出无论如何都会混淆,因为 stdout 没有被锁定。为了获得干净的输出,您可以让线程将消息传递到某个线程安全的共享队列,然后只有一个线程从该队列写入标准输出。
threading.Lock 完全不影响标准输出的使用。它仅用于创建所谓的临界区,其中一次只有一个线程可以执行受同一锁实例保护的所有临界区中的代码。
如果您需要序列化输出,您必须自己实现,可能基于锁或其他机制。
例如,您可以有一个日志记录 class,它在持有某些锁的同时缓冲其他线程的日志记录,但这并非微不足道,因为日志记录 class 不能只是 "check" 如果某个锁正在使用中,因为这会导致竞争条件。一般来说,阻止日志记录并不是一个好主意。但也许您正在考虑 stdout 的其他用途。通常,如果您尝试在多线程程序中生成特定的标准输出,您可能应该明确地为所有输出使用锁或将输出的使用限制为仅一个线程。对于将输出限制为一个线程,queue.Queue 可能会有所帮助,这样多个线程就可以生成完整的部件,然后由一个线程一次打印一个部件。
据我了解,当您在 Python 中实现全局锁时,这应该为激活锁的线程保留 stdout,因此在线程释放锁之前阻止其他线程使用 stdout。
这是否意味着在下面的代码中,线程 "a" 中的循环应该在线程 "b" 中的函数输出任何内容之前完成?当我 运行 它时,线程 "c" 打印的“7”有时会在 "a".
的输出中交错我希望输出始终如下所示:
5
5
5
5
5
6
7
但我得到:
5
7
5
5
5
6
代码:
import threading, time
thelock = threading.Lock()
def afunc(var):
with thelock:
for i in range(5):
time.sleep(.0002)
print(var)
def bfunc(var):
print(var)
a=threading.Thread(target=afunc, args=(5,))
b=threading.Thread(target=bfunc, args=(6,))
c=threading.Thread(target=bfunc, args=(7,))
a.start()
b.start()
c.start()
这是 Python 3.4.3 在 OS X 10.10.3 中。当 运行 直接在 OS X 终端或 PyCharm 4.5.1.
中直接打开文件时,会发生相同的行为你没有实现全局锁,因为没有这样的东西。我的意思是,有但那是 Global Interpreter Lock,它是一种语言功能,而您没有实现它。
吉尔: http://en.wikipedia.org/wiki/Global_Interpreter_Lock
现在,关于您正在实施的锁:
threading.Lock() - returns 一个新的 原始 锁定对象的工厂函数。一旦一个线程获取它,随后尝试获取它阻塞,直到它被释放;任何线程都可以释放它。
查看线程的官方文档:https://docs.python.org/2/library/threading.html
一般来说,当您将某些资源锁定到临界区时,该资源将仅被锁定,线程也必须获得锁才能访问共享资源。在您的示例中,函数 b 在写入标准输出之前不会尝试获取锁。
此外,我相当确定这不会像您预期的那样工作,并且输出无论如何都会混淆,因为 stdout 没有被锁定。为了获得干净的输出,您可以让线程将消息传递到某个线程安全的共享队列,然后只有一个线程从该队列写入标准输出。
threading.Lock 完全不影响标准输出的使用。它仅用于创建所谓的临界区,其中一次只有一个线程可以执行受同一锁实例保护的所有临界区中的代码。
如果您需要序列化输出,您必须自己实现,可能基于锁或其他机制。
例如,您可以有一个日志记录 class,它在持有某些锁的同时缓冲其他线程的日志记录,但这并非微不足道,因为日志记录 class 不能只是 "check" 如果某个锁正在使用中,因为这会导致竞争条件。一般来说,阻止日志记录并不是一个好主意。但也许您正在考虑 stdout 的其他用途。通常,如果您尝试在多线程程序中生成特定的标准输出,您可能应该明确地为所有输出使用锁或将输出的使用限制为仅一个线程。对于将输出限制为一个线程,queue.Queue 可能会有所帮助,这样多个线程就可以生成完整的部件,然后由一个线程一次打印一个部件。