Python3-weakref-weakerf-weakermethod和线程安全性

2024-04-26 15:02:51 发布

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

我正在尝试创建一个简单的回调,它可以从另一个线程注册到一个对象。在本例中,调用回调的初始对象在它自己的线程上运行。在

下面的例子最好地说明了这一点:

from pprint import pprint
import sys
import weakref
import threading
import time

class DummyController(object):

  def __init__(self):
    self.name = "fortytwo"

  def callback(self):
    print("I am number : " + self.name)

class SomeThread(threading.Thread):

  def __init__(self, listener):
    threading.Thread.__init__(self)
    self.listener = listener

  def run(self):
    time.sleep(1)
    dummy = DummyController()
    self.listener.register_callback(dummy.callback)
    time.sleep(5)
    del dummy



class Listener(threading.Thread):

  def __init__(self):
    threading.Thread.__init__(self)
    self.runner = weakref.WeakMethod(self.default_callback)
    self.counter = 20

  def default_callback(self):
    print("Not implemented")

  def register_callback(self, function):
    self.runner = weakref.WeakMethod(function)

  def run(self):
    while self.counter:
      try:
        self.runner()()
      except Exception as e:
        pprint(e)

      self.counter -= 1
      time.sleep(1)



listen = Listener()
some = SomeThread(listen)

listen.start()
some.start()

现在上面的代码可以正常工作了。但我担心这里的线程安全。通读weakref docs,我们不太清楚weakref是否真的是线程安全的,除了下面这行:

Changed in version 3.2: Added support for thread.lock, threading.Lock, and code objects.

我可能根本没看错。我需要添加锁吗,还是所有的东西都是线程安全的?在

非常感谢


Tags: importselftimeinitdefcallbacksleep线程
1条回答
网友
1楼 · 发布于 2024-04-26 15:02:51

好吧,我明白。这不是线程安全的问题,而是weak reference的问题。在

有一个可执行的示例:

from pprint import pprint
import sys
import weakref
import threading
import time
import gc

class SomeThread(threading.Thread):

    def __init__(self, listener):
        threading.Thread.__init__(self)
        self.listener = listener

    def run(self):
        class test:    # simplify this example.
            def callback(self, count):
                print(count)
        time.sleep(1)
        dummy = test()
        self.listener.register_callback(dummy.callback)
        time.sleep(5)
        del dummy
        gc.collect()  # add this line to do garbage collecting.


class Listener(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.runner = weakref.WeakMethod(self.default_callback)
        self.counter = 20

    def default_callback(self):
        print("Not implemented")

    def register_callback(self, function):
        self.runner = weakref.WeakMethod(function)

    def run(self):
        while self.counter:
            try:
                self.runner()(self.counter)
            except Exception as e:
                pprint(e)

            self.counter -= 1
            time.sleep(1)


listen = Listener()
some = SomeThread(listen)

listen.start()
some.start()

输出:

^{pr2}$

如果显式调用gc.collect()callback将丢失其最后一个强引用,然后变成None。由于您永远不知道gc何时收集垃圾,因此存在一个潜在的问题。在

不管您是否使用thread,它只是weak reference的正常行为。在

顺便说一句,注意退出SomeThread.run也会隐式地del dummy,您可以通过移除del dummy并将{}移动到try块来测试它。在

相关问题 更多 >