Fix race conditions in CultureInfo.GetCultureInfoHelper (#26567)
The implementation reads the current value of the static cache field and then later overwrites that field with the originally read value. If ClearCachedData was called in the interim to clear the cached data, this will end up effectively undoing part of that clearing, as it'll end up restoring the previous cache. The fix is to write back the new reference only when we need to, which we could do when we detect it's null.
There's a secondary race condition this fixes as well. When a name and an altname are used with CultureInfo.GetCurrentCulture(string, string), the implementation was publishig the newly created instance into the dictionary under the lock, but then after the lock was released, it was setting that TextInfo to be read-only. That provides a window where another thread could see it as non-read-only and mutate it. The fix is to ensure it's marked as read-only fully before it's published.
As I was doing this, it struck me that the implementation was overly complicated, trying to merge three different code paths for three different callers, presumably to share code, but most of the code ended up not being shared anyway, which just made the code harder to follow for little gain. So, I split it back out into the three calling functions and removed the helper.
I also changed the locking mechanism. It had been using a single shared lock to protect all state, but the purpose of the lock is really just to synchronize access to an individual dictionary, so we can just lock on the relevant dictionary.
Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>