我有以下情况:
- 多线程应用程序
- 我无法控制线程创建。这是由框架管理的(在本例中为 celery)
- 我有一些对象实例化起来很昂贵,而且不是线程安全的。使它们线程安全不是一种选择。
- 对象可以在多个地方实例化,但是如果我在一个已经定义的线程中重新实例化同一个对象,则应该重用该对象。
我想出了以下模式:
#!/usr/bin/env python
import threading
import time
class MyObj1:
def __init__(self, name):
self.name = name
local = threading.local()
def get_local_obj(key, create_obj, *pars, **kwargs):
d = local.__dict__
if key in d: obj = d[key]
else :
obj = create_obj(*pars, **kwargs)
d[key] = obj
return obj
class Worker(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
myobj1 = get_local_obj('obj1', MyObj1, (self.name))
for _ in xrange(3):
print myobj1.name
time.sleep(1)
def test():
ths = [Worker() for _ in xrange(2)]
for t in ths : t.start()
test()
在这里,我自己创建线程,因为这只是一个测试,但如前所述,在实际应用程序中,我无法控制线程。
我感兴趣的是功能get_local_obj
。我有几个问题:
- 这个逻辑会保证对象不在线程之间共享吗?
- 这个逻辑会保证对象在一个线程中不会被多次实例化吗?
- 这个内存会泄漏吗?
- 您对这种方法有什么一般性意见吗?对于上面建议的场景有什么更好的建议吗?
编辑
澄清一下:我的应用程序是多线程的,但不是我在创建线程。我只是在创建一些对象,它们恰好在框架创建的线程中运行。我的一些对象不是线程安全的,所以我只需要为每个线程创建一次。因此get_my_object
。
编辑
local = threading.local() 必须在全局范围内定义。