Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concurrent incrementing of a int variable

A question from a job-interview

int count = 0;

void func1()
{
  for ( int i =0 ; i < 10; ++i )
    count = count + 1;
}

void func2()
{
  for ( int i =0 ; i < 10; ++i )
    count++;
}

void func3()
{
  for ( int i =0 ; i < 10; ++i )
    ++count;
}

int main()
{
  thread(func1);
  thread(func2);
  thread(func3);

  //joining all the threads

  return 0;
}

The question is: what's the range of values count might theoreticaly take? The upper bound apparently is 30, but what's the lower one? They told me it's 10, but i'm not sure about it. Otherwise, why do we need memory barriers?

So, what's the lower bound of the range?

like image 992
fogbit Avatar asked May 07 '13 10:05

fogbit


3 Answers

It's undefined behavior, so count could take on any value imaginable. Or the program could crash.

like image 138
James Kanze Avatar answered Nov 02 '22 13:11

James Kanze


James Kanze's answer is the right one for all practical purposes, but in this particular case, if the code is exactly as written and the thread used here is std::thread from C++11, the behavior is actually defined.

In particular, thread(func1); will start a thread running func1. Then, at the end of the expression, the temporary thread object will be destroyed, without join or detach having been called on it. So the thread is still joinable, and the standard defines that in such a case, the destructor calls std::terminate. (See [thread.thread.destr]: "If joinable() then terminate(), otherwise no effects.") So your program aborts.

Because this happens before the second thread is even started, there is no actual race condition - the first thread is the only one that ever touches count, if it even gets that far.

like image 20
Sebastian Redl Avatar answered Nov 02 '22 11:11

Sebastian Redl


Starting with the easy part, the obvious upper bound is 30 since, if everything goes right, you have 3 calls to functions; each capable of incrementing count 10 times. Overall: 3*10=30.

Ad to the lower bound, they are correct and this is why - the worst-case scenario is that each time that one thread tries to increment count, the other threads will be doing so at exactly the same time. Keeping in mind that ++count actually is the following pseudo code:

count_temp = count;
count_temp = count_temp+1;
count = count_temp;

It should be obvious that if they all perform the same code at the same time, you have only 10 real increments, since they all read the same initial value of count and all write back the same added value.

like image 4
levengli Avatar answered Nov 02 '22 12:11

levengli