【问题标题】:Ruby - class starting a thread is never disposed by GCRuby - 启动线程的类永远不会被 GC 处理
【发布时间】:2017-01-28 15:42:36
【问题描述】:

我是 Ruby 新手,所以如果我遗漏了什么,我深表歉意。我有一个类启动一个线程来执行一些内部缓存刷新。即使我加入线程并将其设置为零,然后将所有类实例设置为零,该类也不会被释放。有没有人看到这个问题?我究竟做错了什么? 谢谢 丹尼尔

我的复制人:

class KK
    def initialize()
      @thread = Thread.new(&method(:refresh_cache))      
      ObjectSpace.define_finalizer( self, self.class.finalize() )
    end

    def self.finalize()
      proc {       
        puts 'Object KK Disposed'
      }
    end

    def wait_thread
      puts 'join thread'
      @thread.join #also tried with exit and kill
      @thread=nil
    end

    def refresh_cache
          puts 'KK still here'    
    end    
end

puts 'started'

puts Thread.list

k2=KK.new
puts    ObjectSpace.each_object(KK).count

puts Thread.list
k2.wait_thread
k2=nil
puts 'After nil'
puts Thread.list

GC.start
sleep 5
#still one instance here
puts    ObjectSpace.each_object(KK).count

【问题讨论】:

    标签: ruby multithreading garbage-collection


    【解决方案1】:
    1. &foo 脱糖到foo.to_proc
    2. &method(:bar) 脱糖到 method(:bar).to_proc
    3. 符号查找必须检索method,这是从Object继承的实例方法,即self.method(:bar).to_proc

    self.method 产生一个 bound Method,它使绑定的接收器(自身)保持活动状态,并且在包装到 proc 中时它会继续这样做。

    如果您想将静态方法转换为可以传递给线程而不保留实例的过程,则应该使用静态方法。

    【讨论】:

    • 非常感谢,我很清楚,因为我有一个绑定到实例方法的线程,所以我打开了一个引用,我的期望是一旦我将线程设置为 nil,引用就会走开,物体本身就可以被处理掉。由于我需要实现的缓存是每个实例(每个实例都是一个设备),我不能使用类方法。我是 Ruby 的新手,但它严重错过了析构函数。
    • GC 异步运行,你不应该期望 立即 处理。
    • 这就是我开始的方式,即使我将线程属性设置为 nil,我也很确定该对象永远不会被释放。无论如何,谢谢大家,我学到了更多 Ruby 内部知识,同时更改了我的设计,以便只创建一个设备实例并在代码的整个生命周期中维护,所以我不再有任何泄漏。
    猜你喜欢
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 2016-10-22
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多