Storm
Storm

Reputation: 4445

I need to create a Thread-safe static variable in C# .Net

ok, its a little more complicated than the question.

class A
{
   static int needsToBeThreadSafe = 0;

   public static void M1()
   {
     needsToBeThreadSafe = RandomNumber();
   }

   public static void M2()
   {
     print(needsToBeThreadSafe);
   }
}

now i require that between M1() and M2() calls 'needsToBeThreadSafe' stays Thread Safe.

Upvotes: 12

Views: 37982

Answers (7)

cosmo
cosmo

Reputation: 241

How About:

public static void M1()
{
    Interlocked.Exchange( ref needsToBeThreadSafe, RandomNumber() );
}

public static void M2()
{
    print( Interlocked.Read( ref needsToBeThreadSafe ) );
}

Upvotes: 24

Henk Holterman
Henk Holterman

Reputation: 273179

To start with I agree with the answers using lock(), that is the safest way.

But there exists a more minimalist approach, your sample code only shows single statements using needsToBeThreadSafe and since int is atomic you only need to prevent caching by the compiler using volatile:

class A
{
   static volatile int needsToBeThreadSafe = 0;

}

But if you need needsToBeThreadSafe to be 'ThreadSafe' over multiple statements, use a lock.

Upvotes: 2

HuBeZa
HuBeZa

Reputation: 4761

You can also use the ReaderWriterLockSlim, that is more efficient for multiple reads and less writes:

static int needsToBeThreadSafe = 0;
static System.Threading.ReaderWriterLockSlim rwl = new System.Threading.ReaderWriterLockSlim();

public static void M1()
{
    try
    {
        rwl.EnterWriteLock();
        needsToBeThreadSafe = RandomNumber();
    }
    finally
    {
        rwl.ExitWriteLock();
    }

}

public static void M2()
{
    try
    {
        rwl.EnterReadLock();
        print(needsToBeThreadSafe);
    }
    finally
    {
        rwl.ExitReadLock();
    }
}

Upvotes: 2

paracycle
paracycle

Reputation: 7850

What you might be trying to ask about is the [ThreadStatic] attribute. If you want each thread that uses the class A to have its own separate value of needsToBeThreadSafe then you just need to decorate that field with the [ThreadStatic] attribute.

For more info refer to the MSDN documentation for ThreadStaticAttribute.

Upvotes: 21

C. Ross
C. Ross

Reputation: 31848

Sound like you need a Volatile member.

static volatile int needsToBeThreadSafe = 0;

Upvotes: 2

Adam Robinson
Adam Robinson

Reputation: 185593

You have two choices: the easiest given your presented code is the volatile keyword. declare needsToBeThreadSafe as static volatile int and that will guarantee that any thread that references that variable will get the "latest" copy, and the variable won't be cached within your code.

That being said, if you want to more generally ensure that M1() and M2() execute "atomically" (or at least exclusively of each other), then you want to use a lock. The cleanest syntax is with a "lock block", like this:

private static object locker = new Object();

//..

public static void M1()
{
    lock(locker)
    {
        //..method body here
    }
}

public static void M2()
{
    lock(locker)
    {
        //..method body here
    }
}

As to which approach to take, that's up to you and should be determined by the code. If all you need is to ensure that a member assignment gets propagated to all threads and isn't cached, then the volatile keyword is simpler and will do the job just fine. If it's beyond that, you may want to go with the lock.

Upvotes: 8

Arsen Mkrtchyan
Arsen Mkrtchyan

Reputation: 50712

class A
{
   static int needsToBeThreadSafe = 0;
   static object statObjLocker = new object();

   public static void M1()
   {
       lock(statObjLocker)
       {
          needsToBeThreadSafe = RandomNumber();
       }
   }

   public static void M2()
   {
       lock(statObjLocker)
       {
          print(needsToBeThreadSafe);
       }
   }
}

Upvotes: 4

Related Questions