12

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.

2
  • 1
    You mean you want the calls to M1() and M2() be atomic? Commented Aug 10, 2009 at 13:04
  • 2
    What do you mean by "stays thread safe"? Commented Aug 10, 2009 at 13:04

7 Answers 7

24

How About:

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

public static void M2()
{
    print( Interlocked.Read( ref needsToBeThreadSafe ) );
}
Sign up to request clarification or add additional context in comments.

1 Comment

I LOVE THIS ONE, is safe and is super fast, SHAME it got only 4 upvotes (mine included) after half decade!
21

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.

5 Comments

I guess everyone else was also right, but for my situation this works perfectly.
Somehow, I just realized that what he is really after is a value that is not shared between Threads. Besides, ThreadStatic is thread-safe since actually no two threads access the same variable (even though it looks like they are).
@paracycle: Good job on answering the question, but eliminating the potential for conflict by creating local copies means that this is, by definition, not "thread safe". While it isn't "unsafe", thread safety means that it properly manages multiple threads dealing with the same resource; I wouldn't say that copying the resource is a means of doing that.
I do get your points and I don't want to needlessly extend the conversation, but my understanding of "thread-safe" is if a piece of code is safe to run simultaneously under multiple threads. "Thread-local storage" is a trivial implementation of that definition and might not suit your needs if you actually need shared data. If what you need is multiple threads of execution without threads stepping on each others' feet, and "thread-local storage" satisfies your needs then it's the way to go. Besides, the Wikipedia article (en.wikipedia.org/wiki/Thread_safety) seems to agree with me.
The thing here is, that it makes a static variable a THREAD-LOCAL variable, but that is still a member of thread-safe set:).
8

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.

Comments

4
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);
       }
   }
}

Comments

2

Sound like you need a Volatile member.

static volatile int needsToBeThreadSafe = 0;

1 Comment

It was 2009 comment, but nowadays it is best to avoid volatile, as it has side effects...
2

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();
    }
}

Comments

2

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.

1 Comment

It was 2009 answer, but nowadays, it would be better to use in answer suggested lock than volatile as volatile has side effects, that tend to create issues easily...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.