Question

I know that declaring a static variable within a function in C means that this variable retains its state between function invocations. In the context of threads, will this result in the variable retaining its state over multiple threads, or having a separate state between each thread?

Here is a past paper exam question I am struggling to answer:

The following C function is intended to be used to allocate unique identifiers (UIDs) to its callers:

get_uid() 
{
static int i = 0;
return i++;
}

Explain in what way get_uid() might work incorrectly in an environment where it is being called by multiple threads. Using a specific example scenario, give specific detail on why and how such incorrect behaviour might occur.

At the moment I am assuming that each thread has a separate state for the variable, but I am not sure if that is correct or if the answer is more to do with the lack of mutual exclusion. If that is the case then how could semaphores be implemented in this example?

Was it helpful?

Solution 2

All the threads of a process share the same address space. Since i is a static variable, it has a fixed address. Its "state" is just the content of the memory at that address, which is shared by all the threads.

The postfix ++ operator increments its argument and yields the value of the argument before the increment. The order in which these are done is not defined. One possible implementation is

copy i to R1
copy R1 to R2
increment R2
copy R2 to i
return R1

If more than one thread is running, they can both be executing these instructions simultaneously or interspersed. Work out for yourself sequences where various results obtain. (Note that each thread does have its own register state, even for threads running on the same CPU, because registers are saved and restored when threads are switched.)

A situation like this where there are different results depending on the indeterministic ordering of operations in different threads is called a race condition, because there's a "race" among the different threads as to which one does which operation first.

OTHER TIPS

Your assumption (threads have their own copy) is not correct. The main problem with code is when multiple threads call that function get_uid(), there's a possible race condition as to which threads increments i and gets the ID which may not be unique.

No, if you want a variable which value depends upon the thread in which it is used, you should have a look at Thread Local Storage.

A static variable, you can imagine it really like a completely global variable. It's really much the same. So it's shared by the whole system that knows its address.

EDIT: also as a comment reminds it, if you keep this implementation as a static variable, race conditions could make that the value i is incremented at the same time by several threads, meaning that you don't have any idea of the value which will be returned by the function calls. In such cases, you should protect access by so called synchronization objects like mutexes or critical sections.

Since this looks like homework, I'll answer only part of this and that is each thread will share the same copy of i. IOW, threads do not get their own copies. I'll leave the mutual exclusion bit to you.

Each thread will share the same static variable which is mostly likely a global variable. The scenario where some threads can have wrong value is the race condition (increment isn't done in one single execution rather it is done in 3 assembly instructions, load, increment, store). Read here and the diagram at the link explains it well.

Race Condition

If you are using gcc you can use the atomic builtin functions. I'm not sure what is available for other compilers.

int get_uid() 
{
    static int i = 0;
    return __atomic_fetch_add(&i, 1, __ATOMIC_SEQ_CST);
}

This will ensure that the variable cannot be acted on by more than one thread at a time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top