我刚从 Python 开始,偶然发现了线程本地内存。我写了一个使用线程的小程序:
#!/usr/bin/env python3
import logging
import signal
import threading
import time
class WorkerThread(threading.Thread):
def __init__(self, idx):
threading.Thread.__init__(self)
self.thread_index = idx
self.thread_alive = True
def run(self):
logging.info(f'Thread {self.thread_index} is starting up!')
while self.thread_alive:
logging.info(f'Thread {self.thread_index} is still running.')
time.sleep(1)
logging.info(f'Thread {self.thread_index} is stopping!')
def kill(self):
self.thread_alive = False
def main():
logging.basicConfig(format = '%(levelname)s: %(message)s', level = logging.INFO)
def signal_handler(sig, frame):
logging.info('Ctrl+c pressed, killing threads and shutting down ...')
nonlocal threads
for thread in threads:
thread.kill()
signal.signal(signal.SIGINT, signal_handler)
logging.info('Signal handler registered, starting threads ...')
threads = []
for i in range(0, 3):
thread = WorkerThread(i)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
signal.signal(signal.SIGINT, signal.SIG_DFL)
if __name__ == '__main__':
main()
该程序按预期工作并打印如下内容:> python3 main.py
INFO: Signal handler registered, starting threads ...
INFO: Thread 0 is starting up!
INFO: Thread 0 is still running.
INFO: Thread 1 is starting up!
INFO: Thread 2 is starting up!
INFO: Thread 1 is still running.
INFO: Thread 2 is still running.
INFO: Thread 0 is still running.
INFO: Thread 1 is still running.
INFO: Thread 2 is still running.
INFO: Thread 0 is still running.
INFO: Thread 2 is still running.
INFO: Thread 1 is still running.
INFO: Thread 2 is still running.
INFO: Thread 1 is still running.
INFO: Thread 0 is still running.
INFO: Thread 1 is still running.
INFO: Thread 2 is still running.
INFO: Thread 0 is still running.
^CINFO: Ctrl+c pressed, killing threads and shutting down ...
INFO: Thread 2 is stopping!
INFO: Thread 1 is stopping!
INFO: Thread 0 is stopping!
在这种情况下,thread_index
和 thread_alive
变量特定于每个线程,因为它们特定于每个对象。但也有threading.local()
创建 thread local memory 的函数.所以我尝试使用它,因为我希望我的变量是线程特定的。我在定义类后使用它:# imports and shebang
class WorkerThread(threading.Thread):
thread_index = threading.local()
thread_alive = threading.local()
# everything else stays the same
但是使用它不会改变任何东西,输出保持不变。所以我的问题是:threading.local()
的用例是什么? ,因为创建对象特定(非静态)变量似乎也有效? 最佳答案
threading.local()
适用于您不能或不想修改实现线程的类的情况。
在上面的示例中,您可以完全控制,因为您已经创建了 WorkerThread
。你已经开始线程了。因此,您知道每个正在运行的线程都有一个实例,并且您可以将值存储在绑定(bind)到线程的实例中。这就是您最初的示例有效的原因。它在这方面工作正常。
但控制线程并不总是如此。有时线程由库或框架启动,您只提供将在这些线程中运行的一些代码。在这种情况下,您不能修改 Thread
类并向它们添加线程特定的变量。
让我们以多线程 Web 服务器为例。您提供应该处理传入请求的函数。您无需创建所有基础设施来监听套接字、解析 http 请求等。所有这些事件都由框架处理。它为您启动一个线程池,当有传入请求时,框架会解析它并使用池中的线程调用您提供的处理程序。
在这种情况下,假设您想为正在处理的请求(例如当前登录的用户)存储一些上下文,以便您可以在请求处理期间访问它,但不需要在每个函数中显式地传递它。您不能添加此 currentUser
变量到线程类,因为您无法控制它。但是你可以使用 threading.local()
存储它。在多个线程中同时处理的请求将拥有自己的副本。
这同样适用于您自己的创作。当程序变得更复杂并且您需要将基础架构代码(管理线程)与应用程序的逻辑分开时,您可能不想将线程特定变量添加到线程类并使用 threading.local()
反而。
关于python - 何时在 Python 中使用线程本地内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64157133/