0x03 线程专有状态
问题
有些情况下, 我们需要保存当前运行线程的专有状态, 而且这个状态对其他线程是不可见的, 即其他线程不会对这个状态产生影响, 做出修改. 在这多线程程序中是很常见的需求.
可以通过threading.local()创建一个线程本地存储对象, 将需要保存的变量, 以这个对象属性的形式进行保存和读取. 只对当前运行的线程可见, 其他线程无法感知.
使用方法
以socket
编程为例, 每个线程管理一个独立的socket, 以避免相互之间的干扰.
import threading
from functools import partial
from socket import socket, AF_INET, SOCK_STREAM
class LazyConnection:
def __init__(self, address, family=AF_INET, types=SOCK_STREAM):
self.address = address
self.family = family
self.type = types
self.local = threading.local()
print("type of local:", type(self.local))
def __enter__(self):
if hasattr(self.local, "sock"):
raise RuntimeError("already connected")
self.local.sock = socket(self.family, self.type)
self.local.sock.connect(self.address)
return self.local.sock
def __exit__(self, exc_ty, exc_val, tb):
self.local.sock.close()
del self.local.sock
def test(conn):
with conn as s:
s.send(b"GET /index.html HTTP/1.0\r\n")
s.send(b"Host: www.python.org\r\n")
s.send(b"\r\n")
res = b"".join(iter(partial(s.recv, 8192), b""))
print("Got {} bytes".format(len(res)))
conn = LazyConnection(("www.python.org", 80))
t1 = threading.Thread(target=test, args=(conn,))
t2 = threading.Thread(target=test, args=(conn,))
t1.start()
t2.start()
t1.join()
t2.join()
输出为:
type of local: <class '_thread._local'>
Got 392 bytes
Got 392 bytes
所有线程都公用一个LazyConnection
的实例. 实例对象的local
属性供每个线程单独使用, 每个线程将自己所操作的独立的socket
保存为local
对象的sock
属性. 这样LazyConnection
就能安全地用于多线程环境中了.
每个线程实际上都创建了自己专属的socket
连接, 以self.local.sock
的形式保存. 当不同的线程在socket
上执行操作时, 它们并不会互相产生影响, 因为它们都是在不同的socket
上完成操作的.
最后更新于
这有帮助吗?