About a week ago I posted about IsolatedStorage and Thread Safety and what exactly the statement Any instance members are not guaranteed to be thread safe means in the documentation of the class libraries.
A lot of discussion making superstitious claims about serializing access to instance members ensued, however all of those led to illogical conclusions, implying that it was never possible to write a program that used multiple threads.
Eventually, I contacted members of the Base Class Library team who responded with the following definitive statements:
In general, the overall Framework guidance should apply to IsolatedStorage as well.
- Static members should be thread safe.
- Instance members cannot be expected to be thread safe unless otherwise specified.
- Instance members on different instances should be safe to use concurrently.
In addition, specifically related to IsolatedStorage, I got this definitive statement:
If you work on distinct instances of IsolatedStorage / ..File / ..Stream on different threads you will not run into any concurrency issues.
Different instances of those types have private copies of all internal data; and in cases where we need to update global state (e.g. isolated storage quota) we do all the necessary locking for you.
Note, however, that if you open two distinct Stream instances on the same file – whether through the iso storage or directly thought FileStream, we do not make any guarantees about the order in which these instances will access the underlying physical file. When using two distinct stream instances on the same file concurrently from different threads, you may end up with interleaved, mixed or invalid data in the file. However, the stream objects themselves will remain consistent and valid.
This is different from using one single Stream object from different threads: That is not supported and can break the stream object itself, not only resulting in data corruption, but also in weird runtime behaviour.
So there you have it. Put your mutexes and locks down and step away from the code face and think!
If you are seeing what looks like a threading problem, and you found a mutex or lock solved it, it probably has, but not for the reason you thought. There is probably some other multithreading logic error you had not foreseen, and your lock will either kill performance, or just make the bug even harder to find.