2012-11-02 59 views
0

我有一個列表與對象列表<> my_objects。多個線程可以更改此列表。假設我沒有任何鎖定機制來控制對列表的訪問。併發訪問列表:如果刪除對象或列表設置爲空,會發生什麼情況?

如果我正在處理列表中的某個對象,並且另一個線程突然將該數組設置爲null,會發生什麼?

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); 
+3

您很可能會得到一個'InvalidOperationException',並且顯示消息「在枚舉器被實例化後集合被修改了。」 –

+0

它是一個數組還是一個列表?他們不是一回事。 –

+0

看看System.Collections.Concurrent命名空間對象...你可能會直接掉線,這將是線程安全的。這並不回答一個問題,只是想我會指出。 – iMortalitySX

回答

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時,它將保存對同一對象的第二個引用。然後您清除my_objects,這意味着您不能再通過my_objects參考實際對象。但是這並沒有改變你仍然有o的事實,你仍然可以通過o來引用實際的對象。 (而反過來暗示該對象本身仍然存在,C#是一種垃圾收集語言,第一次近似意味着對象保證一直保留,直到完成它們爲止。在這方面不同,和Objective-C是在第三個方式不同。不是說你問。)

實際上,在這方面,引用MyObject表現就像原始的類型,如int。如果我有int一個數組,而我呢

int oi = my_ints[i]; 

話,我可以做我想做的事情與my_ints(清除它,從中取出物品),並且不會改變oi仍然存在的事實。

事情大約引用類型MyObject,你糊塗了足夠的問這個問題的原因,是與MyObject兩個變量(omy_objects[i])仍然同實際的對象,因此,如果您通過my_objects[i].gainSpiderPowers()突變對象,無論您是通過my_objects[i]還是通過o查看,都會看到該突變的影響。

1

在這兩種情況下,您都已獲得對該對象的引用,並且更改該列表對該對象本身沒有影響。由於對象本身的狀態(例如NullReferenceException),您不會得到任何異常。

但是,由於併發訪問List<T>,您可能會遇到其他異常。您應該在訪問列表時使用鎖定,或者更好地查看System.Collections.Concurrent名稱空間中的類。

+0

不正確。 'my_objects [i]'只有在其他線程同時讀取時纔是安全的。當他們也寫(變異)所有投注都關閉。 –

+0

@HenkHolterman我讀到這個問題的方式,OP關心的是列表更改_past_那行代碼。 –

-1

由於List<>被記錄爲不是線程安全的,因此您'不使用任何鎖定',結果是列表中的競爭條件。

你可以得到各種例外,我見過空引用索引超出界限

基本上,語義是'未定義的'。

3

如果我正在處理列表中的對象並突然另一個線程將數組設置爲null,會發生什麼?

沒有,如果您已經將問題的引用複製到局部變量。

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

o的值就是對該對象的引用:

如果另一個線程設置my_objects前空這行你會得到一個異常。它具有沒有知道您碰巧得到它的列表或數組。收集可以被垃圾收集,任何事情都可能發生 - 參考和對象本身都不會受到影響。

(從列表中元素的去除可能導致問題,因爲亨克說 - List<T>不是線程安全的 - 但是這從一個不同的事情我知道你在問什麼。)

+0

謝謝。我對兩種情況都感興趣(設置爲空和刪除對象)。 – curiosity

+1

@curiosity:在這兩種情況下,變量「o」或其值的變化都沒有。 –

0

考慮使用ReadOnlyCollection。它位於System.Collections.ObjectModel命名空間中。

相關問題