Race conditions when adding to, but not reading from, a List<T> (or Stack or Queue) - what happens?

邮差的信 提交于 2021-02-05 09:13:25

问题


Note: I'm asking this question relative to the 3.5 framework, so I'm not including any of the newer multithreaded constructs in 4.0 (which I'm still learning).

I've been trying to come up with an answer on this to try and close out an argument I've been having, but I don't feel like I've found a conclusive description as to what would or could happen in the following scenario.

Say you have an app with multiple threads that are all generating objects, with each thread generating a unique object. There's a single instance of a collection (List, Stack, or Queue) that's the repository for the objects once they've been created, and the objects are effectively immutable once added to the collection.

During this process, the only operation on the collection is adding items. There's no reading, removing, or counting done. It doesn't matter what the order of the items are in the collection.

The question is, if there is no locking around the collection when the individual threads are trying to add objects, is that really a problem?

I say yes, but pretty much all of the textbook descriptions of why race conditions are problematic have a read on one end and a race on the other or are writing to a single variable, so I don't have enough evidence to argue my case effectively.

My reason for saying yes is basically down to the fact that the collections are not designed to be thread safe, so you could wind up with unexpected or undefined behavior, even if only "writes" are being performed. I'd guess that there is a risk that two threads might try adding their object to the same slot in the collection, and therefore you'd loose an object when it gets overwritten, but I haven't found anything that says that it is indeed possible. Or that there might be some behind-the-scenes problems, such as when the collection needs to grow itself to accommodate more items.

Can someone provide me with some information to help put this argument to rest? I'm especially interested to hear if there's anything that would prove me wrong.


回答1:


Adding items to a List<T> (or stack, etc) is not thread-safe.

This involves

  • Checking if internal array size is sufficient
  • If not, create a new array, copy all items
  • Set item in the array with the index equal to the length of the List<T>

None of the above processes are thread safe and there are no synchronisation in .NET framework code. So if you do not synchronise, I guarantee your list will be corrupted.




回答2:


Adding items to a list involves reading and writing of memory so unless there is synchronization there is a race.




回答3:


You're basically right, although some of the simpler structures like a stack or queue might be "accidentally" thread safe. You have no guarantee on how the "internals" of any collection are implemented. For example, a list is backed by an array. If you add a new item that causes it to grow the array, it will (could) copy all of the values to a new larger array. This is probably thread safe in its implementation, but since it's not a threadsafe object, there's no contract to its thread safety.



来源:https://stackoverflow.com/questions/5728688/race-conditions-when-adding-to-but-not-reading-from-a-listt-or-stack-or-que

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!