【问题标题】:Will an instance be garbage collected if a thread which was created by it is still running?如果由它创建的线程仍在运行,实例是否会被垃圾收集?
【发布时间】:2020-06-10 09:30:05
【问题描述】:
public class ServiceA
{
    public ServiceA()
    {
        Task.Run(() =>
        {
            while (true) { }
        });
    }
}

public class Program
{
    public void Main()
    {
        new ServiceA(); // new ServiceA without any variable referencing to it

        //...
        //...
        //...
        //...
        //...
        //...
        //...
        //...
        //...
        //...
        //...

        Console.WriteLine("Would 'new ServiceA()' still alive and won't be GC"
            + " since its task is still running?");
    }
}

请考虑上面的代码。我想知道ServiceA 的实例是否会是 GC,因为它总是“诞生”一个永远不会结束的任务。但是,我根本没有提及Task。 (即this.task1 = Task.Run(/.../))。这是否意味着即使ServiceA instance 被GC,Task 仍然存在?

【问题讨论】:

    标签: c# multithreading reference garbage-collection task


    【解决方案1】:

    它生成的任务与 ServiceA 的关系为零,因此它显然不会阻止 ServiceA 被收集。重要的不是某种神秘的从前关系,而是垃圾收集器在执行时可以看到的关系。如果线程有一个变量包含对 ServiceA 实例的引用,则它可以安全地被收集,但这样的集合不在您的代码中。

    【讨论】:

    • 我不懂 C#,但在某种其他语言中,我希望 lambda 表达式创建的任务对象可能包含对 ServiceA() 方法创建它的实例的隐式引用。
    • @SolomonSlow 似乎您在谈论与内部类存在此类问题的某种其他语言。由于此代码示例没有内部类,而只有一个 lambda 表达式,因此即使使用某种其他语言,也不会阻止 ServiceA 实例的集合。事实上,甚至没有阻止任务对象进行垃圾收集。只有代表本机线程资源的对象肯定会留在内存中。
    • @Holger,换句话说,你是说因为 lambda 表达式没有引用它出现的类的任何成员,所以 保证捕获this。是当然。我现在不打算验证这一点,但我去寻找那个保证,书面,在我编写任何依赖它的代码之前是的。
    • @SolomonSlow for Java,你不会在规范中找到它,但规范对其他行为保持沉默,即内部类也总是捕获this。问题是,哪种行为实际上需要保证,对象被阻止进行垃圾回收(即,当有终结器时,它的终结器不会运行)或者垃圾回收是可能的(仍然不能保证它实际上发生了,即使发生了,仍然不能保证它的终结器会运行)。
    猜你喜欢
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 2020-05-18
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    相关资源
    最近更新 更多