Search code examples
cmultithreadingconcurrencystaticmutual-exclusion

Static Variables and Threads (C)


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?


Solution

  • 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.