2

如果“安全”是一个误导性的词,我很抱歉,我不确定在这种情况下使用什么词。我想知道例如是否使用

 public static List<myObj> myList = new List<myObj>();

在 C# 中是可以接受的。无论如何,静态变量在应用程序的整个生命周期中都存在于 RAM 中,因此例如在 ASPX 等应用程序中,这可能会导致一些不需要的行为,并且 GC 不会收集分配。

我注意到,如果我有一个静态的对象列表,比如一个静态的“全局”类,即。

 globl.myList.add(foo);

然后它们会在应用程序的整个生命周期中保持不变。这是否意味着如果我有一个静态对象列表,那么附加到列表中的对象本身就是静态的,还是因为有对它们的引用,GC 不收集它们?换句话说,如果我删除了一个元素,GC 会稍后收集它还是会卡在堆中直到应用程序死亡?

提前谢谢!

4

5 回答 5

4

安全在这里是一个非常非常可疑的术语。在什么情况下安全?

就内存而言是否安全:大多static如果稍后删除该引用并且没有其他人引用它,则添加对列表的引用仍然是可收集的,因此将项目添加到static列表本身并不会阻止它被收集。

现在,也就是说如果该项目static在所有引用消失之前被列表持有很长时间,它可能会在 GC 生命周期中被提升到后面的世代,这可能会使项目的内存清理速度变慢很多。参考文献被释放。

就线程安全而言是否安全:大多数情况下没有. 如果列表是可修改的,而其他线程可以读取它,那么您将需要同步对它的访问。也就是说,如果列表在创建时加载,多个线程可以安全地以“只读”方式访问它。

而且,如果您确实需要对可变集合进行并发访问,请考虑使用 .NET 4.0 中的并发集合 ( MSDN )

于 2012-10-26T15:17:03.357 回答
1

消极的。只要引用以这种方式保存,GC 就不会在您的列表中收集引用。

对象本身并不是“静态的”——它们只是相对于静态引用而存在。

于 2012-10-26T15:17:27.700 回答
1

只有列表是静态的。对象不是。如果您删除了一个对象并且没有其他对该内存的引用,那么它将成为垃圾收集的候选对象。

于 2012-10-26T15:18:59.843 回答
1

无论如何,静态变量在应用程序的整个生命周期中都存在于 RAM 中

它们在AppDomain的整个生命周期中都在内存中- 对于 IIS 来说,这意味着AppPool的生命周期。IIS 将定期回收 AppPools,因此无法保证数据将无限期地保留在内存中。

这是否意味着如果我有一个静态对象列表,那么附加到列表中的对象本身就是静态的,还是因为有对它们的引用,GC 不收集它们?

不,对象不是静态的——它们没有被收集,因为有对它们的引用。

如果我删除一个元素,GC 会稍后收集它还是会卡在堆中直到应用程序死亡?

只要有东西引用它,就不会收集 if 。如果列表是唯一引用它,则一旦从列表中删除它就有资格进行 GC。

于 2012-10-26T15:20:18.873 回答
0

如果我删除一个元素,GC 会稍后收集它还是会卡在堆中直到应用程序死亡?

您可以创建实验,您可以编写一个程序,加载像位图这样的大图像并将其添加到列表中,然后将其从列表中删除,然后启动 gc 收集,您可以在任务管理器(cntr+shift+esc)内存中看到使用您的应用程序。例如:

class Program
    {
        public static List<Bitmap> Bitmaps = new List<Bitmap>(); 

        static void Main(string[] args)
        {
            Bitmaps.Add((Bitmap) Image.FromFile(@"C:\\image.bmp")); // the size of image 23 mb (in that case), you will see in task manager that you app start consumes a lot of memory
            Console.WriteLine("Memory state after loading image in list");
            Console.ReadKey();
            Bitmaps.RemoveAt(0);
            GC.Collect();
            Console.WriteLine("Memory after collect"); // and after deletion from list and start gc you will see that your app consume  less memory
            Console.ReadKey();
        }
    }

这意味着 GC 将在从列表中删除后收集您的元素。

于 2012-10-26T15:39:05.140 回答