Consider the following code, which takes place in a background thread (“thread B”):
List<T> invocationQueueCopy;
lock (invocationQueue)
{
invocationQueueCopy = invocationQueue;
invocationQueue = new List<T>();
}
In another thread (“thread A”) I simply lock “invocationQueue” before adding to it:
lock (invocationQueue)
{
invocationQueue.Add(args);
}
I have read that reference assignment is atomic, but could it ever occur that “thread A” will end up writing to the old list (the one replaced in “thread B”) after receiving the lock? I have read other answers that imply it could, if the value of the reference were stored in a register on “thread A” then it would not know that “thread B” had modified the value in the class. If this is so, would declaring “invocationQueue” volatile prevent this?
Notes:
- I know I could clone then clear the list.
- I
know I could have a separate lock
object for the list.
But I’d rather not do either of these things unless it is required.
Thanks in advance.
Edit:
Just to clarify from Adam’s comments: invocationQueue is a private field which is created internally to this class and never exposed to the outside world so nothing could lock on it except these two methods.
EDIT: Your solution will work. Lock creates a full fence so any caching is prevented, basically meaning you’ll always get the most recent value for the list reference. The only thing, as suggested in the comments is the fact that you should do the locking on a neutral object, not the list itself.
The following is wrong!! But I let it here anyway to show how fu*** hard threading might be… the fact is the following reasoning is defeated by the fact that lock creates a full fence.