diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs index 91264247bc9539..478029174db339 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs @@ -9,6 +9,7 @@ using System.Text.Json.Serialization; using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; +using System.Threading; namespace System.Text.Json { @@ -29,11 +30,14 @@ public sealed partial class JsonSerializerOptions [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)] private static void RootReflectionSerializerDependencies() { - if (s_defaultSimpleConverters is null) + // s_typeInfoCreationFunc is the last field assigned. + // Use it as the sentinel to ensure that all dependencies are initialized. + if (Volatile.Read(ref s_typeInfoCreationFunc) is null) { s_defaultSimpleConverters = GetDefaultSimpleConverters(); s_defaultFactoryConverters = GetDefaultFactoryConverters(); - s_typeInfoCreationFunc = CreateJsonTypeInfo; + // Explicitly ensure that the previous fields are initialized along with this one. + Volatile.Write(ref s_typeInfoCreationFunc, CreateJsonTypeInfo); } [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)] diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 95199d7ead9c54..8837b55dcf5da5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -9,6 +9,7 @@ using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; +using System.Threading; namespace System.Text.Json { @@ -579,7 +580,7 @@ internal MemberAccessor MemberAccessorStrategy /// /// Whether the options instance has been primed for reflection-based serialization. /// - internal bool IsInitializedForReflectionSerializer { get; private set; } + internal bool IsInitializedForReflectionSerializer; /// /// Initializes the converters for the reflection-based serializer. @@ -589,7 +590,7 @@ internal MemberAccessor MemberAccessorStrategy internal void InitializeForReflectionSerializer() { RootReflectionSerializerDependencies(); - IsInitializedForReflectionSerializer = true; + Volatile.Write(ref IsInitializedForReflectionSerializer, true); if (_cachingContext != null) { _cachingContext.Options.IsInitializedForReflectionSerializer = true; @@ -610,7 +611,9 @@ private JsonTypeInfo GetJsonTypeInfoFromContextOrCreate(Type type) return null!; } - Debug.Assert(s_typeInfoCreationFunc != null); + Debug.Assert( + s_typeInfoCreationFunc != null, + "Reflection-based JsonTypeInfo creator should be initialized if IsInitializedForReflectionSerializer is true."); return s_typeInfoCreationFunc(type, this); }