import threading
import time
class A:
b = 1
my_obj = A()
def worker():
my_obj.b = 2
new_thread = threading.Thread(target=worker, name="new_thread")
new_thread.start()
time.sleep(1)
# 主线程
print(my_obj.b)
# 打印结果为2
# 因为my_obj是主线程和新线程共享的对象
将my_obj实例化改为使用Local线程隔离对象
import threading
import time
from werkzeug.local import Local
class A:
b = 1
my_obj = Local()
my_obj.b = 1
def worker():
my_obj.b = 2
print("in new thread b is: ", my_obj.b)
new_thread = threading.Thread(target=worker, name="new_thread")
new_thread.start()
time.sleep(1)
print("in main thread b is:", my_obj.b)
class LocalStack(object):
"""This class works similar to a :class:`Local` but keeps a stack
of objects instead. This is best explained with an example::
>>> ls = LocalStack()
>>> ls.push(42)
>>> ls.top
42
>>> ls.push(23)
>>> ls.top
23
>>> ls.pop()
23
>>> ls.top
42
They can be force released by using a :class:`LocalManager` or with
the :func:`release_local` function but the correct way is to pop the
item from the stack after using. When the stack is empty it will
no longer be bound to the current context (and as such released).
By calling the stack without arguments it returns a proxy that resolves to
the topmost item on the stack.
.. versionadded:: 0.6.1
"""
def __init__(self):
# 内部维护了一个Local对象作为私有变量
self._local = Local()
def __release_local__(self):
self._local.__release_local__()
def _get__ident_func__(self):
return self._local.__ident_func__
def _set__ident_func__(self, value):
object.__setattr__(self._local, '__ident_func__', value)
__ident_func__ = property(_get__ident_func__, _set__ident_func__)
del _get__ident_func__, _set__ident_func__
def __call__(self):
def _lookup():
rv = self.top
if rv is None:
raise RuntimeError('object unbound')
return rv
return LocalProxy(_lookup)
# 提供了push,pop方法,实际上就是在操作Local中的一个Stack
def push(self, obj):
"""Pushes a new item to the stack"""
rv = getattr(self._local, 'stack', None)
if rv is None:
self._local.stack = rv = []
rv.append(obj)
return rv
def pop(self):
"""Removes the topmost item from the stack, will return the
old value or `None` if the stack was already empty.
"""
stack = getattr(self._local, 'stack', None)
if stack is None:
return None
elif len(stack) == 1:
release_local(self._local)
return stack[-1]
else:
return stack.pop()
@property
def top(self):
"""The topmost item on the stack. If the stack is empty,
`None` is returned.
"""
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None
Local,Local Stack,字典的关系
Local使用字典的方式实现了线程隔离 Local Stack封装了Local对象,将其作为自己的一个属性,实现了线程隔离的栈结构