1

I have seen an interview question as below: What's the possible range of the result of the following code:

void ThreadProc(int& sum)
{
    for (int i = 1; i <= 50; i++)
    {
        sum += 1;
    }
}

int main()
{
    int sum = 0;
    thread t1(ThreadProc, std::ref(sum));
    thread t2(ThreadProc, std::ref(sum));
    t1.join();
    t2.join();
    cout << sum << '\n';
    return 0;
}

The given answer is [50,100]. However, I thought it should be [2,100]. If given sequence as below, sum will be 2.

  1. thread t1 get the cpu, and load the initial sum=0 into cache (let's say the cached sum is c1, its value is 0 now).
  2. thread t2 get the cpu, and increase (49 times), and now the sum will be 49.
  3. thread t1 get the cpu, and compute sum = c1 + 1, now sum is 1.
  4. thread t2 get the cpu, and load the sum (=1) and compute sum + 1 and cached the result (c1 is 2 now). Before the c1 is written to variable sum by t1, t2 preempt the cpu.
  5. thread t2 get the cpu, and increase (1 times) [and now the sum will be x (the value does't matter)], then thread t2 finished.
  6. thread t1 get the cpu, and write the cached result c1 to sum, now sum is 2.

    Am I right?

ricky
  • 2,058
  • 4
  • 23
  • 49

1 Answers1

1

This code causes undefined behaviour because sum is modified from two different threads without any concurrency protection. This is called a data race in the C++ Standard.

Therefore any behaviour whatsoever is possible (including but not limited to all the cases you mention).

Link to cppreference page about memory model.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • is it the same in other popular language, such as c#, Java – ricky Nov 08 '18 at 04:27
  • @ricky this answer only applies to C++. The situation would be similar in C, and I don't know about any other languages – M.M Nov 08 '18 at 04:28
  • If you like more details, you could look into safe, regular and atomic registers. Since most modern day behaviors are atomic(are they?) in their loads and stores, the value of [2, 100] seems like a correct answer in a practical sense. Obviously the standard says its undefined behavior due to data race, and so, as per the standard it might display arbitrary values like 345, but pragmatically I don't think you'll get any value outside [2, 100]. Please correct me because I might be horribly wrong. – Sahil Dhoked Nov 08 '18 at 09:31