Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are static variables thread-safe? C#

Tags:

c#

.net

asp.net

I want to create a class which stores DataTables, this will prevent my application to import a list of details each time I want to retrieve it. Therefore this should be done once, I believe that the following code does so, but I am not sure if it is thread-safe.

The below code is in the Business Layer Section of my three tier application, it is returning a DataTable to the Presentation Layer.

public class BusinessLayerHandler {     public static DataTable unitTable;     public static DataTable currencyTable;      public static DataTable GetUnitList()     {         //import lists each time the application is run         unitTable = null;         if (unitTable == null)         {             return unitTable = DatabaseHandler.GetUnitList();         }         else         {             return unitTable;         }     }      public static DataTable GetCurrencyList()     {         //import lists each time the application is run         currencyTable = null;         if (currencyTable == null)         {             return currencyTable = DatabaseHandler.GetCurrencyList();         }         else         {             return currencyTable;         }     } 

Any help is appreciated, if there is a better way how to cache a DataTable please let me know.

Update:

Thanks to your opinions, this is the suggested method to do it, if I understood correctly:

public class BusinessLayerHandler {     private static DataTable unitTable;     private static DataTable currencyTable;      private static readonly object unitTableLock = new object();     private static readonly object currencyTableLock = new object();      public static DataTable GetUnitList()     {         //import lists each time the application is run         //unitTable = null;          lock (unitTableLock)         {             if (unitTable == null)                {                 return unitTable = DatabaseHandler.GetUnitList();             }         }         return unitTable;     }      public static DataTable GetCurrencyList()     {         //import lists each time the application is run         lock (currencyTableLock)         {             if (currencyTable == null)             {                 return currencyTable = DatabaseHandler.GetCurrencyList();             }         }         return currencyTable;     } } 
like image 583
Ryan S Avatar asked Aug 04 '11 12:08

Ryan S


People also ask

Is a static variable thread safe?

Static variables are not thread safe. Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.

Do threads share static variables in C?

Each thread will share the same static variable which is mostly likely a global variable.

Are local variables thread safe in C?

Local variables are stored on the stack, each thread has a reference to its own set of variables on the stack, so local variables are thread safe. Yes.


2 Answers

It appears as though all you want to do is load it once and keep a reference to it. All you need to guard is initialising the variable if it's null. Null checking, locking and null checking again is called Double Check Locking and will work well for you. It's best practice to provide a separate locking object, so you have good control over granularity of locks.

Note this doesn't stop people from mutating the value inside the DataTable it only stops people from trying to initialise the static member at the same time.

private static readonly object UnitTableLock = new object(); private static DataTable unitTable; private static bool _ready = false;  public static DataTable GetUnitList() {     if (!_ready)     {         lock (UnitTableLock)         {             if (!_ready)             {                 unitTable = new DataTable; //... etc                 System.Threading.Thread.MemoryBarrier();                 _ready = true;             }         }     }      return unitTable; } 

Only read from the result of GetUnitList never write to it.

Amended with reference to http://en.wikipedia.org/wiki/Double-checked_locking

like image 102
Adam Houldsworth Avatar answered Sep 24 '22 01:09

Adam Houldsworth


I thought it would be worth adding that Double Check Locking has since been implemented in .net framework 4.0 in a class named Lazy. So if you would like your class to include the locking by default then you can use it like this:

public class MySingleton {     private static readonly Lazy<MySingleton> _mySingleton = new Lazy<MySingleton>(() => new MySingleton());      private MySingleton() { }      public static MySingleton Instance     {         get         {             return _mySingleton.Value;         }     } } 
like image 30
Lloyd Powell Avatar answered Sep 24 '22 01:09

Lloyd Powell