0

我有一个包含对象List<> my_objects的列表。多个线程可以更改此列表。假设我没有任何锁定机制来控制对列表的访问。

如果我正在使用列表中的一个对象并且突然另一个线程将数组设置为空,会发生什么情况?

    MyObject o = my_objects[i];

    //now a second thread has set my_objects to null
    o.myMethod();

会发生 NullPointerException 吗?

此外,如果第二个线程在我在第一个线程中使用它时从列表中删除了考虑的对象,会发生什么?

   //second thread:
   //y = i
   MyObject o2 = my_objects[y];

   my_objects.Remove(o2);
4

4 回答 4

3

如果我正在使用列表中的一个对象并且突然另一个线程将数组设置为空,会发生什么情况?

没什么,如果您已经将相关引用复制到局部变量。

如果在此行之前my_objects另一个线程设置为 null ,您将收到异常:

MyObject o = my_objects[i]; // my_objects must be non-null

的值o只是对对象的引用。它知道您碰巧从中获取它的列表或数组。收集可能是垃圾收集,任何事情都可能发生 - 引用和对象本身都不会受到影响。

(正如 Henk 所说,从列表中删除元素可能会导致问题 -List<T>不是线程安全的 - 但这与我理解你所问的问题不同。)

于 2012-11-02T19:45:31.663 回答
1

在这两种情况下,您已经获得了对该对象的引用,并且更改列表对对象本身没有影响。由于对象本身的状态(例如 NullReferenceException),您不会得到任何异常。

但是,由于同时访问List<T>. 您应该在访问列表时使用锁定,或者更好的是,查看System.Collections.Concurrent命名空间中的类。

于 2012-11-02T19:44:19.377 回答
1
MyObject o = my_objects[i];

//now a second thread has set my_objects to null, and/or invoked my_objects.Remove(o)
o.myMethod();

没关系。该变量my_objects保存对对象的引用,而不是对象本身。当您创建一个新变量o时,它会保存对同一对象的第二个引用。然后你 clear my_objects,这意味着你不能再引用实际的对象my_objects了。但这并不能改变您仍然拥有的事实,您仍然o可以通过o. (反过来又意味着对象本身仍然存在。C# 是一种垃圾收集语言,这首先意味着对象保证会一直存在,直到你用完它们。非托管 C++ 在在这方面,Objective-C 在第三个方面有所不同。不是你问的。)

实际上,在这方面,引用的 MyObject行为就像原始类型一样,如int. 如果我有一个数组int,我会

int oi = my_ints[i];

然后我可以做任何我想做的事情my_ints(清除它,从中删除项目),这不会改变oi仍然存在的事实。

关于引用类型的事情MyObject,以及你对这个问题感到困惑的原因是,MyObject两个变量 (omy_objects[i]) 仍然引用同一个实际对象,所以如果你通过 改变对象my_objects[i].gainSpiderPowers(),你会看到效果无论您是查看 viamy_objects[i]还是 via ,该突变都会发生o

于 2012-11-02T19:54:47.373 回答
0

考虑使用 ReadOnlyCollection。它位于 System.Collections.ObjectModel 命名空间中。

于 2012-11-02T19:45:48.983 回答