DEV Community

Discussion on: Where is Your Data?

Collapse
ac000 profile image
Andrew Clayton

Hi,

In this example

static struct {
   int n_someFuncCalled;
   /* Other stuff */
} S;

int someFunc()
{
   ++S.n_someFuncCalled;
   /* Works no matter how many threads */
   return 0;
}

The comment

 /* Works no matter how many threads */

is a bit misleading. I'm not entirely sure what it's relating to, but if it's saying that multiple threads can simultaneously increment the counter and the result will be correct, then I'm afraid that's not true.

You would need to protect that counter with a mutex or somesuch or use an atomic type.

Collapse
jrbrtsn profile image
John Robertson Author

Incrementing an integer is atomic.

Collapse
ac000 profile image
Andrew Clayton

Hmm, OK, an integer can generally be considered atomic as when it's updated, you always see either it's old or new value and not something inbetween.

However this does not help with the case of multiple threads trying to update an integer. Using a normal int type and doing a ++ on it will be three instructions; load/add/store.

So

++S.n_someFuncCalled;

translates to something like the following assembly

        movl    S(%rip), %eax
        addl    $1, %eax
        movl    %eax, S(%rip)

Lets say the counter has a value of 10 and two threads are coming to increment it.

So thread a could be between the add and second mov, when thread b comes in and does the first mov.

So thread A did 10 + 1, but before it copied the result back to memory, thread B came in and copied 10 into the register and then does the add, meanwhile thread A has now put 11 back into memory (correct), however thread B is doing 10 + 1 and so also puts 11 back in memory, so we are left with a = 11 and not 12...

This from the link I provided above also gives a hint

Objects of atomic types are the only objects that are free from data races, that is, they may be modified by two threads concurrently or modified by one and read by another.

This is easy to test yourself with a small program that has two threads updating an integer, try with and without locking... the example in the link above shows what you can expect to see...

Thread Thread
jrbrtsn profile image
John Robertson Author • Edited on

You are correct, thanks for pointing out the oversight. I got the 20 minute lecture this morning from my son, and specifying atomic is the best practice for code to work on a variety of hardware platforms. Thanks for pointing this out!