使用静态列表和链接列表是否安全?

时间:2012-10-26 15:14:34

标签: c# asp.net

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

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

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

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

 globl.myList.add(foo);

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

提前致谢!

5 个答案:

答案 0 :(得分:4)

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

在内存方面安全多数是。添加对static列表的引用仍然可以收集,如果该引用稍后被删除而没有其他人引用它,那么将项添加到static列表本身并不会阻止它从被收集。

现在,表示,如果项目在所有引用消失之前已被static列表保留了很长时间,那么它可能会在GC生命周期中被提升为后代,一旦所有引用都被释放,这可能会使项目的内存清理速度慢很多。

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

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

答案 1 :(得分:1)

否定。只要以这种方式保存引用,GC就不会收集列表中的引用。

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

答案 2 :(得分:1)

只有List是静态的。对象不是。如果删除一个对象并且没有对该内存的其他引用,则它将成为垃圾回收的候选对象。

答案 3 :(得分:1)

  

无论什么

,静态变量都会在应用程序的整个生命周期中保留在RAM中

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

  

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

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

  

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

只要有东西引用它就不会被收集。如果列表是唯一的引用它,一旦从列表中删除它就有资格获得GC。

答案 4 :(得分:0)

  

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

你可以创建实验,你可以编写一个程序,加载大图像,如位图,并将其添加到列表,并从列表中删除,然后启动gc collect,你可以在任务管理器中看到(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会在从列表中删除后收集您的元素。