简体   繁体   中英

thread safe static class

I would like to know if the following static class would be thread safe or not and why?

public static class Settings
{
    public static string AStringSetting { get; set; }
    public static int AIntSetting { get; set; }

    public static void Load()
    {
        // load values from database
    }
}

I have a multithread windows service that loads the setting a the start of the service. I would like to add some kind of auto refresh in my service. I made some test running 200+ threads reading and writing the public properties and I was not able to make the process crash...

Is that class thread safe? Why?

Just because you couldn't make your program crash doesn't mean that your class is thread safe. Check http://en.wikipedia.org/wiki/Thread_safety . In your case race conditions can occur, because access to your properties is not synchronized.

I'm no expert on threading but afaik thread safety is not about crash-prevention. It's more about reliable results. In your code example your properties AStringSetting and AIntSetting are never used, so it's not possible to determine if there may be a threading issue. Consider this code:

if (AStringSetting.Equals("TEST"))
{
    // AStringSetting may not be "TEST" anymore, although it was until a moment ago. 

    if (AIntSetting < 10)
    {
       // no idea what AIntSetting contains now. It was below 10 just a moment ago, though.
       AIntSetting = AIntSetting + 1;
    }
}

this code would not be thread safe. For instance, another thread could modify one of the two properties while the first line is executed. Or worse, after the first line has been executed. Depending on what that code would do, you could end up with inconsistent results. You would not be able to rely on the fact that you just tested the contents of AStringSetting and AIntSetting , because you never know if another thread didn't just change them.

To make your class thread safe, you should implement a thread locking mechanism and let all methods use that mechanism (in your case that could be a private static Object and the lock command) to block access to the static properties from other threads. Your getters and setters should also use that locking mechanism to make sure properties are neither read nor changed from different threads.

 private static string mStringSetting;
 public static string AStringSetting { 
     get{
         lock(mThreadLock) { return mStringSetting; }
     } 
     set {
         lock(mThreadLock) { mStringSetting = value; }
     }
 }

 private static int mIntSetting;
 public static int AIntSetting { 
     get{
         lock(mThreadLock) { return mIntSetting; }
     } 
     set {
         lock(mThreadLock) { mIntSetting = value; }
     }
 }
 private static Object mThreadLock = new Object();

 public static void IncreaseIntIfLowerThan10AndStringIsTest()
 {
     lock(mThreadLock)
     {
         if (AStringSetting.Equals("TEST"))
         {
             // AStringSettig is still "TEST", no other thread can change it due to the lock
             if (AIntSetting < 10)
             {
                 AIntSetting = AIntSetting + 1;
             }
         }
     }
 }

And even that may not be enough if the properties have some kind of logic connection and depend on another. If that is the case, you may have to implement thread safe methods implementing your business logic in one, thread-safe step and block at least write-access to the properties from outside the class altogether.

You might want to look at the answer here: https://stackoverflow.com/a/435045/896697 . Jon Skeet makes a really interesting point that in certain cases the JIT compiler can cache values. And since your point is to get the latest ( or current ) version of that application setting, you might not reach your goal ( regardless of thread-safety ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM