Are read-only CultureInfo objects thread-safe?
Asked Answered
F

1

1

Preface: I know how to create a read-only CultureInfo object. That is not the question and it has been answered in detail here:

Note that the text of that question is similar to this one, but the answers are completely different. Before thinking about closing this question as a duplicate of the other one, please consider the fact that none of the answers in the other question answers this question.


My question:

Is it thread-safe to access instance members of a read-only CultureInfo object?

Reasons to assume that it is:

  • If it weren't, using instance members of CultureInfo.InvariantCulture or objects retrieved by CultureInfo.GetCultureInfo wouldn't be thread-safe, and a lot of code would break.

  • The community seems to think so (see Henk's comment on this answer), but does not explain why.

Reasons to assume that it isn't:

Falk answered 21/4, 2016 at 10:19 Comment(9)
The documentation pages always include a note about thread safety near the end. Did you check it? Besides, thread-safety is a concern only when modifying an object. It isn't a concern with read-only objects or when the only access is for readingSulphuric
Why are you asking this question? Did you encounter a problem? As for MSDN, it does state that static members are thread safe. InvariantCulture is a static, as is GetCultureInfo().Sulphuric
Finally, if you want a better explanation, just check the source codeSulphuric
@PanagiotisKanavos: Yes, I checked it, it contains just the default disclaimer. I've clarified that in the question. I know that getting InvariantCulture is static, but accessing InvariantCulture.Calendar, for example, is a member access, and, thus, not guaranteed to be thread-safe.Falk
Unless it's only for reading. Given that the source is available you can check it directly, but simply returning a value from a backing field is thread safeSulphuric
@PanagiotisKanavos: True, but implementations might change. That's why "design by contract" exists. :-)Falk
Yes, and in this case reading isn't supposed to change anything. In fact, you could argue that any field access method is not thread safe even if the code actually is, because someone may change it in the future to regenerate the field or something.Sulphuric
On the other hand, with open source code, the code is the contract.Sulphuric
@PanagiotisKanavos: If you plan to never upgrade your libraries, sure. ;-) On a more serious note: I actually don't think closed/open source makes a difference here; design by contract is about the division of responsibility between user and library. If a method's contract states that it returns a list of user names (and nothing else), the library developer has the freedom to return them in a different order in the next version without telling anyone. If he decides to return a list of user objects instead, he breaks the contract and must declare this as a breaking change.Falk
S
2

Thread safety is an issue when you are altering an object, so the question is: are you altering the object or does something happen inside the CultureInfo that could change its state.

MSDN isn't particularly clear about this: it just shows the default notice about thread-safety.

So we have to find out ourselves. Luckily, the CultureInfo class is made available through the reference source. There you will find it will load the culture data at the start of the method, and cache that result inside the CultureInfo class.

The initialization of properties is not thread-safe. See for example the NumberFormat property: it can instantiate two instances due to concurrent calls. There is no locking!

There are more problems at some places, for example the NumberFormat property again, where you can change its properties. Inside that class it checks if it is writable or not, so if you are using default cultures (the read-only ones, like InvariantCulture) there is no thread-safety issue. In all other cases we can't assume it is thread-safe.

Conclusion: they are not thread-safe.

Steeplejack answered 21/4, 2016 at 10:31 Comment(7)
But it should be threadsafe, otherwise as the OP points out, you could never safely use CultureInfo.InvariantCulture since there is only one instance of it, and you'd never know if another thread (perhaps in an entirely separate class library) was using it. I suppose Microsoft could have made an egregious error with CultureInfo.InvariantCulture, but I'm pretty sure they didn't, and accessing it is indeed threadsafe.Bringhurst
But that one is safe since you can't change its state. Its backing data is read-only. If you create your own CultureInfo, you could end up in trouble with multi-threading and lazy loading of NumberFormat for example. @MatthewWatsonSteeplejack
Ah I see, your conclusion is talking about non-read-only CultureInfo. I was confused because the OP was asking only about read-only ones. To be clear, is your answer to the question "Is it thread-safe to access instance members of a read-only CultureInfo object?" Yes?Bringhurst
You could end up with two NumberFormat instances, but since they are read-only internally, there isn't an issue.Steeplejack
@MatthewWatson for your edited comment: basically yes, but not entirely since there could still be two instances of the same backing info.Steeplejack
@PatrickHofman NumberFormat probably is thread-safe for read-only CultureInfo objects.. The only modification is assigning a fully initialized object to the backing field. Even if this happens twice, the two objects will be identical as long as they are generated from the same m_CultureData fieldSulphuric
They have the same fields but they are not identical. Comparing for equality is one thing that goes wrong @panSteeplejack

© 2022 - 2024 — McMap. All rights reserved.