线程间Python共享类实例

2024-09-28 21:01:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类,它将所有资源加载到应用程序所需的内存中(主要是图像)。

然后几个线程需要通过这个类访问这些资源。 我不希望每个实例都重新加载所有资源,所以我认为我使用了Singleton模式。 我是这样做的:

class DataContainer(object):
    _instance = None
    _lock = threading.Lock()
    _initialised = True

    def __new__(cls, *args, **kwargs):
        with cls._lock:
            if not cls._instance:
                cls._initialised = False
                cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self, map_name = None):

        # instance has already been created
        if self._initialised:
            return

        self._initialised = True

        # load images

只要我不使用多个线程,这就可以正常工作。但是对于多线程,每个线程都有不同的实例。所以使用4个线程,每个线程创建一个新实例。 我希望所有线程都使用这个类的同一个实例, 所以资源只加载到内存中一次。

我还尝试在定义类的同一模块中执行此操作,但在类定义之外:

def getDataContainer():
    global dataContainer
    return dataContainer

dataContainer = DataContainer()

但是每个线程仍然有自己的实例。

我是python新手,如果这是错误的方法请告诉我, 我很感激你的帮助


Tags: 实例instance内存selfnonelockreturnobject
1条回答
网友
1楼 · 发布于 2024-09-28 21:01:28

要展开@Will的注释,如果父线程创建了“共享对象”,然后将其传递给每个线程,则所有线程都将共享同一对象。

(对于进程,请参见multiprocessing.Manager类,该类直接支持共享状态,包括修改)

import threading, time


class SharedObj(object):
    image = 'beer.jpg'


class DoWork(threading.Thread):
    def __init__(self, shared, *args, **kwargs):
        super(DoWork,self).__init__(*args, **kwargs)
        self.shared = shared

    def run(self):
        print threading.current_thread(), 'start'
        time.sleep(1)
        print 'shared', self.shared.image, id(self.shared)
        print threading.current_thread(), 'done'


myshared = SharedObj()
threads = [ DoWork(shared=myshared, name='a'), 
            DoWork(shared=myshared, name='b')
]
for t in threads:
    t.start()
for t in threads:
    t.join()
print 'DONE'

输出:

<DoWork(a, started 140381090318080)> start
<DoWork(b, started 140381006067456)> start
shared beer.jpg shared140381110335440
 <DoWork(b, started 140381006067456)> done
beer.jpg 140381110335440
<DoWork(a, started 140381090318080)> done
DONE

注意,线程id是不同的,但它们都使用相同的SharedObj实例,在以440结尾的内存地址处。

相关问题 更多 >