Hi, all

Recently I am playing with multithread programming, and I find that we
cannot use static variables in thread function.The first thread can
start but the second just freeze. Could anybody tell me why?

#include "stdafx.h"
#include "process.h"
#include "windows.h"

void func(void* szName)
{
// if this static is removed, then everything goes OK.
static int a = 1;
while(a<10)
{
printf("%s:%d\n", szName, a++);
}
}

int main(int argc, char* argv[])
{
printf("thread1 starts\n");
_beginthread(func, 0, "t1");
printf("thread2 starts\n");
_beginthread(func, 0, "t2");
Sleep(5000);
return 0;
}



this is the output:

thread1 starts
thread2 starts
t1:1
t1:2
t1:3
t1:4
t1:5
t1:6
t1:7
t1:8
t1:9
Press any key to continue

Re: static variables cannot be used in multithread functions? by Victor

Victor
Wed Oct 25 09:15:59 CDT 2006

BruceWho wrote:
> Hi, all
>
> Recently I am playing with multithread programming, and I find that we
> cannot use static variables in thread function.The first thread can
> start but the second just freeze. Could anybody tell me why?
>
> #include "stdafx.h"
> #include "process.h"
> #include "windows.h"
>
> void func(void* szName)
> {
> // if this static is removed, then everything goes OK.
> static int a = 1;
> while(a<10)
> {
> printf("%s:%d\n", szName, a++);

Add
Sleep(100);

here, see if it makes any difference.

> }
> }
>
> int main(int argc, char* argv[])
> {
> printf("thread1 starts\n");
> _beginthread(func, 0, "t1");
> printf("thread2 starts\n");
> _beginthread(func, 0, "t2");
> Sleep(5000);
> return 0;
> }
>
>
>
> this is the output:
>
> thread1 starts
> thread2 starts
> t1:1
> t1:2
> t1:3
> t1:4
> t1:5
> t1:6
> t1:7
> t1:8
> t1:9
> Press any key to continue

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask



Re: static variables cannot be used in multithread functions? by Ulrich

Ulrich
Wed Oct 25 09:21:12 CDT 2006

F'up set to comp.os.ms-windows.programmer.win32, please do that yourself
next time.

BruceWho wrote:
> Recently I am playing with multithread programming, and I find that we
> cannot use static variables in thread function.

That's not true, but I think you're not precisely saying what you mean.

> void func(void* szName)
> {
> // if this static is removed, then everything goes OK.
> static int a = 1;
> while(a<10)
> {
> printf("%s:%d\n", szName, a++);
> }
> }

Well, define "OK" first! The point is that a function-static var is a global
variable with a local scope, nothing else. So, like all globals, it is
shared between threads.

> int main(int argc, char* argv[])
> {
> printf("thread1 starts\n");
> _beginthread(func, 0, "t1");
> printf("thread2 starts\n");
> _beginthread(func, 0, "t2");
> Sleep(5000);
> return 0;
> }
>
>
>
> this is the output:
>
> thread1 starts
> thread2 starts
> t1:1
> t1:2
> t1:3
> t1:4
> t1:5
> t1:6
> t1:7
> t1:8
> t1:9
> Press any key to continue

Totally normal output for that program. Thread 1 increments 'a' to 10 before
thread 2 even gets a timeslice, so thread 2 doesn't do anything eventually.

Uli



Re: static variables cannot be used in multithread functions? by Ben

Ben
Wed Oct 25 13:02:02 CDT 2006


> Totally normal output for that program. Thread 1 increments 'a' to 10
> before
> thread 2 even gets a timeslice, so thread 2 doesn't do anything
> eventually.

Note that because the variable isn't declared volatile, there are many
different potential outputs, including:

t1:1
t1:2
t1:3
t1:4
t1:5
t2:6
t2:7
t2:8
t2:9
t1:6
t1:7
t1:8
t1:9

or

t1:1
t1:2
t1:3
t1:4
t1:5
t2:1
t2:2
t2:3
t2:4
t2:5
t2:6
t2:7
t2:8
t2:9
t1:6
t1:7
t1:8
t1:9

Because the compiler is free to read a into a register once at the beginning
of the function and not read it again, and may or may not write the updated
value back to a until the return statement.

If you want each thread to count from 1 to 9 exactly once, you might be
looking for __declspec(thread). If you want each number hit, in order, by
exactly one thread (though different number could be processed on different
threads), use volatile.



Re: static variables cannot be used in multithread functions? by Doug

Doug
Wed Oct 25 13:46:09 CDT 2006

On Wed, 25 Oct 2006 13:02:02 -0500, "Ben Voigt" <rbv@nospam.nospam> wrote:

>Note that because the variable isn't declared volatile, there are many
>different potential outputs, including:

<snip>

>Because the compiler is free to read a into a register once at the beginning
>of the function and not read it again, and may or may not write the updated
>value back to a until the return statement.

The function in question was this:

void func(void* szName)
{
// if this static is removed, then everything goes OK.
static int a = 1;
while(a<10)
{
printf("%s:%d\n", szName, a++);
}
}

Practically speaking, the compiler has to update "a" in memory unless it
can prove that calling printf doesn't reenter func.

>If you want each thread to count from 1 to 9 exactly once, you might be
>looking for __declspec(thread). If you want each number hit, in order, by
>exactly one thread (though different number could be processed on different
>threads), use volatile.

Using volatile won't guarantee that. You would need to use a mutex or an
atomic operation such as InterlockedIncrement.

--
Doug Harrison
Visual C++ MVP

Re: static variables cannot be used in multithread functions? by BruceWho

BruceWho
Wed Oct 25 21:39:16 CDT 2006

If we declare variable a this way:

__declspec(thread) static int a = 1;

then output is:

thread1 starts
thread2 starts
t1:1
t1:2
t1:3
t1:4
t1:5
t1:6
t1:7
t1:8
t1:9
t2:1
t2:2
t2:3
t2:4
t2:5
t2:6
t2:7
t2:8
t2:9
Press any key to continue

So, the variable a is not shared by the two threads. And now I get
another question: if __declspec(thread) is used, is what the compiler
actually does allocating two global(static) variable for each thread?

Ben Voigt wrote:
> > Totally normal output for that program. Thread 1 increments 'a' to 10
> > before
> > thread 2 even gets a timeslice, so thread 2 doesn't do anything
> > eventually.
>
> Note that because the variable isn't declared volatile, there are many
> different potential outputs, including:
>
> t1:1
> t1:2
> t1:3
> t1:4
> t1:5
> t2:6
> t2:7
> t2:8
> t2:9
> t1:6
> t1:7
> t1:8
> t1:9
>
> or
>
> t1:1
> t1:2
> t1:3
> t1:4
> t1:5
> t2:1
> t2:2
> t2:3
> t2:4
> t2:5
> t2:6
> t2:7
> t2:8
> t2:9
> t1:6
> t1:7
> t1:8
> t1:9
>
> Because the compiler is free to read a into a register once at the beginning
> of the function and not read it again, and may or may not write the updated
> value back to a until the return statement.
>
> If you want each thread to count from 1 to 9 exactly once, you might be
> looking for __declspec(thread). If you want each number hit, in order, by
> exactly one thread (though different number could be processed on different
> threads), use volatile.


Re: static variables cannot be used in multithread functions? by Carl

Carl
Wed Oct 25 21:44:41 CDT 2006

BruceWho wrote:
> If we declare variable a this way:
>
> __declspec(thread) static int a = 1;
>
> then output is:
>
> thread1 starts
> thread2 starts
> t1:1
> t1:2
> t1:3
> t1:4
> t1:5
> t1:6
> t1:7
> t1:8
> t1:9
> t2:1
> t2:2
> t2:3
> t2:4
> t2:5
> t2:6
> t2:7
> t2:8
> t2:9
> Press any key to continue
>
> So, the variable a is not shared by the two threads. And now I get
> another question: if __declspec(thread) is used, is what the compiler
> actually does allocating two global(static) variable for each thread?

Sort of, but not exactly. What it's actually doing is declaring a single
static variable that's an index into a per-thread table of variables that's
allocated and maintained by the OS. In this case, '__declspec(thread)
static int a;' and 'int a;' are effectively the same - each creates a unique
variable for each thread - the difference being that the value of the static
(or per-thread static) is retained between calls to the functionn, while the
ordinary "automatic" variable is re-initialized each time the function is
entered.

-cd



Re: static variables cannot be used in multithread functions? by BruceWho

BruceWho
Thu Oct 26 01:04:06 CDT 2006

I wonder if variable a is allocated in heap segment as usual static
variables if it's declared this way:

__declspec(thread) static int a;

Carl Daniel [VC++ MVP] wrote:
> >
> > So, the variable a is not shared by the two threads. And now I get
> > another question: if __declspec(thread) is used, is what the compiler
> > actually does allocating two global(static) variable for each thread?
>
> Sort of, but not exactly. What it's actually doing is declaring a single
> static variable that's an index into a per-thread table of variables that's
> allocated and maintained by the OS. In this case, '__declspec(thread)
> static int a;' and 'int a;' are effectively the same - each creates a unique
> variable for each thread - the difference being that the value of the static
> (or per-thread static) is retained between calls to the functionn, while the
> ordinary "automatic" variable is re-initialized each time the function is
> entered.
>
> -cd


Re: static variables cannot be used in multithread functions? by Carl

Carl
Thu Oct 26 01:12:36 CDT 2006

BruceWho wrote:
> I wonder if variable a is allocated in heap segment as usual static
> variables if it's declared this way:
>
> __declspec(thread) static int a;

No, nothing realted to such a variable is allocated from the heap. There's
a true static variable and a slot in the TLS array for each thread. The TLS
array is basically an extension of the kernel's per-thread data structure
and exists whether you store anything in it or not.

-cd



Re: static variables cannot be used in multithread functions? by Arnaud

Arnaud
Thu Oct 26 01:14:12 CDT 2006

"Doug Harrison [MVP]" <dsh@mvps.org> a écrit dans le message de news:
87cvj2hqqatpu9444n8fsomrc5ikic06ok@4ax.com...
> On Wed, 25 Oct 2006 13:02:02 -0500, "Ben Voigt" <rbv@nospam.nospam> wrote:

>
> Using volatile won't guarantee that. You would need to use a mutex or an
> atomic operation such as InterlockedIncrement.

volatile would be enough on VC 2005, since it gives a memory fence semantic
to all accesses to the variable. Anyway, this is non-standard, specific to
VC2005 and can't be relied upon if portability is of any concern.

Arnaud
MVP - VC



Re: static variables cannot be used in multithread functions? by Arnaud

Arnaud
Thu Oct 26 01:15:44 CDT 2006


"BruceWho" <Bruce.Who.HK@gmail.com> a écrit dans le message de news:
1161842646.506048.74610@f16g2000cwb.googlegroups.com...
>I wonder if variable a is allocated in heap segment as usual static
> variables if it's declared this way:
>
> __declspec(thread) static int a;

It's allocated in TLS (Thread Local Storage)

Arnaud
MVP - VC



Re: static variables cannot be used in multithread functions? by Bruno

Bruno
Thu Oct 26 02:09:21 CDT 2006

> If we declare variable a this way:
>
> __declspec(thread) static int a = 1;

I just want to add that you should never do that if you are building a DLL.
__declspec(thread) makes it impossible to delay load or dynamically load a
DLL that uses it.
In that case you should use the TLS functions instead.

--

Kind regards,
Bruno van Dooren
bruno_nos_pam_van_dooren@hotmail.com
Remove only "_nos_pam"



Re: static variables cannot be used in multithread functions? by Doug

Doug
Thu Oct 26 11:03:46 CDT 2006

On Thu, 26 Oct 2006 08:14:12 +0200, "Arnaud Debaene"
<adebaene@club-internet.fr> wrote:

>"Doug Harrison [MVP]" <dsh@mvps.org> a écrit dans le message de news:
>87cvj2hqqatpu9444n8fsomrc5ikic06ok@4ax.com...
>> On Wed, 25 Oct 2006 13:02:02 -0500, "Ben Voigt" <rbv@nospam.nospam> wrote:
>
>>
>> Using volatile won't guarantee that. You would need to use a mutex or an
>> atomic operation such as InterlockedIncrement.
>
>volatile would be enough on VC 2005, since it gives a memory fence semantic
>to all accesses to the variable. Anyway, this is non-standard, specific to
>VC2005 and can't be relied upon if portability is of any concern.

To accomplish what was claimed, you need an atomic load/modify/store
operation, and memory barriers don't provide that. Note also that memory
barriers are relevant only on (some) multiprocessor machines. With or
without memory barrier semantics, volatile is not useful here.

--
Doug Harrison
Visual C++ MVP

Re: static variables cannot be used in multithread functions? by Tim

Tim
Sat Oct 28 01:10:50 CDT 2006

"BruceWho" <Bruce.Who.HK@gmail.com> wrote:
>
>Recently I am playing with multithread programming, and I find that we
>cannot use static variables in thread function.The first thread can
>start but the second just freeze. Could anybody tell me why?

You've received good information on how to make this do what you want, but
I'm wondering if you understand now how your results happened. The second
thread didn't freeze, it's just that the first thread happened to get a
shot at the CPU first, and made it all the way through 10 loops. By the
time it was done, the static "a" was set to 10, so when the second thread
got a chance to run, "a<10" was already false, so it skipped the loop.
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.