4

E.g., can the following code ever print "3" for one of the threads?

int foo() { static int a = 1; return ++a; } void thread1() { cout<<foo()<<endl; } void thread2() { cout<<foo()<<endl; } 

edit: It's C++ 98

12
  • Because even if they're shared, race conditions might cause it to print "2" every time for both threads, so I might be mislead. Commented Oct 18, 2012 at 10:14
  • No, how should that be possible. It will always print 2. And there is no race-condition, because the initialization of a is automatically synchronized. Commented Oct 18, 2012 at 10:16
  • @nosid because of this: blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx , but it seems to be from 2004 so I'm not sure. Commented Oct 18, 2012 at 10:16
  • 1
    @nosid: It is? Automatically synchronized by which mechanism? Commented Oct 18, 2012 at 10:17
  • 3
    It is rather pointless asking about threads in versions of C++ prior to C++11, because they simply did not exist (as far as the standard and the language was concerned). Commented Oct 18, 2012 at 10:21

2 Answers 2

8

Of course it can print 3. It is even the "usual semantics" of this code to do so. Thread 1 initializes it with 1 and increments it, so it is 2. Thread 2 increments it again, so it is 3.

So, yes, scoped static variables are static, i.e., global variables. They are shared by threads.

Of course, the code has a race condition, so the result can possibly be anything, but 3 is a possible result.

Sign up to request clarification or add additional context in comments.

3 Comments

The code has undefined behaviour (due to the race condition in ++a), so there are no "usual semantics".
still, you will get 3 on most compilers in most situations. But you are right, "usual semantics" is a quite strange word which is not defined anyway, so I placed it in quotes now... Btw: In C++11, the semantics of a program with race conditions is not fully undefined.
Race conditions are definitely fully undefined -- see [intro.multithread]/21: The execution of a program contains a data race if it contains two conflicting actions in dierent threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.
3

local static variables are shared between threads.

Initialisation of function-local static variables is thread-safe in C++11 (before that, threads did not even exist ;)).

Modification of function-local static variables, on the other hand, is not thread-safe, so your modified code has undefined behaviour (due to the race condition).

9 Comments

So they're not shared? If I let one thread wait a second and let the other execute first, the waiting thread will still print 2?
The key here is "C++11". Is the OP using C++11? He didn't mention it. I think we're still at the point where somebody says if they're using C++11, as most people and most production environments are not. And then this initialisation is absolutely not thread-safe.
@TravisG "So they're not shared?" - No, they are shared. It's only the initialization that is thread-safe (I don't know this, but I believe Mankarse here), so you won't have two threads trying to initialize the variable. The variable itself is shared and even if you synchronize the access, you still have one thread printing 2 and the other 3. And without synchronization it's UB, anyway, as said in the answer.
@LightnessRacesinOrbit, good compilers have had thread-safe init of statics for years, long before C++11 - you can't say "absolutely" whether the init is safe
@JonathanWakely: In the real world, you can't just "change it" because your code relies on thread-safe function-static initialisation instead of using the appropriate locks suggested by the lack of an implementation guarantee. In the real world, your choice of toolchain comes down to many, many more factors than that and switching toolchains potentially has significant consequences elsewhere. Lots of people have been able to rely on thread-safe init if, like I said, they know for a fact that their version of GCC makes it safe -- I suspect many only think that they can rely on it.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.