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.
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.
Adding items to a list involves reading and writing of memory so unless there is synchronization there is a race.
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.
精彩评论