| Severity | Warning |
| Reported by | PostSharp.Patterns.Threading |
| Message | Thread-safety policy: static field <Field> must be read-only, or be marked as [ExplicitlySynchronized] or [ThreadStatic]. |
Cause
A static field is shared by all threads. When any thread can assign it, two threads can see different values, or a thread can see a value that another thread has only partly initialized. When you add the ThreadSafetyPolicy attribute to an assembly, PostSharp therefore checks the static fields of every class and reports THR026 for each static field that is not readonly.
The policy does not check constants, compiler-generated fields, such as the backing field of a static automatic property, fields marked as ExplicitlySynchronizedAttribute and fields marked as ThreadStaticAttribute. A field that is not read-only and whose type is not thread-safe also gets THR027.
In the following example, the DefaultCurrency static field is not read-only.
using System;
using PostSharp.Patterns.Threading;
[assembly: ThreadSafetyPolicy]
namespace Errors.THR026_Error;
public static class StoreSettings
{
// Any thread can assign this static field, so the policy requires it to be read-only.
public static string DefaultCurrency = "EUR";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( $"Default currency: {StoreSettings.DefaultCurrency}" );
}
}
warning THR026: THR026_Error.cs(11,26): Thread-safety policy: static field Errors.THR026_Error.StoreSettings.DefaultCurrency must be read-only, or be marked as [ExplicitlySynchronized] or [ThreadStatic].
Resolution
- When the field does not change after its initialization, make it
readonly. - When the program must change the field, and every access to it is synchronized in your code, for example with a
lockstatement, mark it as ExplicitlySynchronizedAttribute. - When each thread needs its own value, mark the field as ThreadStaticAttribute.
In the following example, the field is readonly.
using System;
using PostSharp.Patterns.Threading;
[assembly: ThreadSafetyPolicy]
namespace Errors.THR026_Fixed;
public static class StoreSettings
{
// The field is read-only, so no thread can assign it after the static constructor.
public static readonly string DefaultCurrency = "EUR";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( $"Default currency: {StoreSettings.DefaultCurrency}" );
}
}
Default currency: EUR
See Also
Reference
ThreadSafetyPolicy
ExplicitlySynchronizedAttribute
Other Resources