单例 单例,多线程才是单例,在多进程单例无效,大家帮解释?

单例 单例,多线程才是单例,在多进程单例无效,大家帮解释?

import multiprocessing
import threading
import time


def singleton(cls):
    _instance = {}

    def inner():
        if cls not in _instance:
            _instance[cls] = cls()
        return _instance[cls]

    return inner


@singleton
class Cls(object):
    count = 0

    def __init__(self):
        self.count += 1


def run1():
    for i in range(0, 100):
        a = Cls()
        a.count += 1
        b = Cls()
        b.count += 1
        b = Cls()
        b.count += 1
        time.sleep(1)
        print("a", a.count)


def run2():
    for i in range(0, 100):
        a = Cls()
        a.count += 1
        b = Cls()
        b.count += 1
        b = Cls()
        b.count += 1
        time.sleep(1)
        print("b", a.count)


if __name__ == '__main__':
    threading.Thread(target=run1).start()
    threading.Thread(target=run2).start()
    # multiprocessing.Process(target=run1).start()
    # multiprocessing.Process(target=run2).start()
阅读 967
2 个回答

首先加两行代码在你的原有代码中:

import multiprocessing
import threading
import time


def singleton(cls):
    _instance = {}

    def inner():
        if cls not in _instance:
            _instance[cls] = cls()
        return _instance[cls]

    return inner


@singleton
class Cls(object):
    count = 0

    def __init__(self):
        self.count += 1


def run1():
    for i in range(0, 100):
        a = Cls()
        a.count += 1
        b = Cls()
        b.count += 1
        b = Cls()
        b.count += 1
        time.sleep(1)
        print("a", a.count, "id:", id(b))    # 改动


def run2():
    for i in range(0, 100):
        a = Cls()
        a.count += 1
        b = Cls()
        b.count += 1
        b = Cls()
        b.count += 1
        time.sleep(1)
        print("b", a.count, "id:", id(b))    # 改动


if __name__ == '__main__':
    threading.Thread(target=run1).start()
    threading.Thread(target=run2).start()
    # multiprocessing.Process(target=run1).start()
    # multiprocessing.Process(target=run2).start()

你自行打印一下就能看到,多线程下的两个 print 下的 id 是一样的,多进程的则只能保证单个进程的id一致,两个进程下的这个 id 并不同。

造成这种差异的原因是python的多进程内存空间是不共享的,每一个进程都有一个单独的python解释器在背后运行,也就是你在A进程操作的对象,在B进程默认你是无法访问的,他们彼此之间互相独立,内存地址也不同。

而多线程不同,多线程都在同一个进程下,所以内存空间共享,单例在线程间是有效的。

这个问题的本质在于以下几点:

  1. 线程与进程的区别:进程是操作系统分配和调度资源的基本单位,线程是进程的一条执行路径,这里的资源包含内存。
  2. 单例的含义:单例是指单一的对象,而对象本质上是内存中具有特定结构的数据,所以单例只存在于一块特定的内存中。
  3. Python的多线程:threading库创建的多线程是同一个Python解释器进程中的多个线程对象,它们共享该进程的内存;而multiprocessing库创建的多进程是多个Python解释器进程,这些进程管理的内存是相互独立的。
  4. Python多进程实现单例:使用multiprocessing.shared_memory创建共享内存,然后将单例对象放在共享内存中。
  5. 补充说明:上面提到,多个进程是多个Python解释器进程,这里假设了运行Python程序使用标准CPython,如果是其它运行时如Jython,则表现可能有所不同,需要专门验证。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题