0

オブジェクトList<>my_objectsを含むリストがあります。複数のスレッドがこのリストを変更できます。リストへのアクセスを制御するためのロックメカニズムがないとします。

リストのオブジェクトを操作していて、突然別のスレッドが配列をnullに設定した場合はどうなりますか?

    MyObject o = my_objects[i];

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

NullPointerExceptionは発生しますか?

さらに、最初のスレッドで作業しているときに、2番目のスレッドが考慮されたオブジェクトをリストから削除するとどうなりますか?

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

   my_objects.Remove(o2);
4

4 に答える 4

3

What happens, if I'm working with an object of the list and suddenly another thread sets the array to null?

Nothing, if you've already copied the reference in question to a local variable.

You'll get an exception if another thread sets my_objects to null before this line:

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

The value of o is just a reference to the object. It has no knowledge of the list or array you happened to get it from. The collection could be garbage collected, anything could happen - neither the reference nor the object itself is affected.

(The removal of the element from the list could cause problems, as Henk says - List<T> is not thread safe - but that's a different matter from the one I understand you were asking about.)

于 2012-11-02T19:45:31.663 に答える
1

In both cases, you've already got a reference to the object, and changing the list has no effect on the object itself. You won't get any exceptions because of the state of the object itself (e.g. NullReferenceException).

However you may get other exceptions because of the concurrent access to the List<T>. You should either use locking when accessing the list or, even better, take a look at the classes in the System.Collections.Concurrent namespace.

于 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();

That's fine. The variable my_objects holds references to objects, not the objects themselves. When you make a new variable o, it holds a second reference to the same object. Then you clear my_objects, which means you can't refer to the actual object through my_objects anymore. But that doesn't change the fact that you still have o, and you can still refer to the actual object through o. (And that in turn implies that the object itself still exists. C# is a garbage-collected language, which, to a first approximation means that objects are guaranteed to stick around until you're done with them. Non-managed C++ is different in this respect, and Objective-C is different in yet a third way. Not that you asked.)

Effectively, in this respect, references to MyObject behave just like primitive types like int. If I have an array of int, and I do

int oi = my_ints[i];

then I can do whatever I want with my_ints (clear it, remove items from it) and that won't change the fact that oi still exists.

The thing about reference types like MyObject, and the reason you got confused enough to ask this question, is that with MyObject both variables (o and my_objects[i]) still refer to the same actual object, so if you mutate the object via my_objects[i].gainSpiderPowers(), you'll see the effects of that mutation no matter whether you're looking via my_objects[i] or via o.

于 2012-11-02T19:54:47.373 に答える
0

Consider using a ReadOnlyCollection. It is located in the System.Collections.ObjectModel namespace.

于 2012-11-02T19:45:48.983 に答える