DEV Community

Discussion on: Where is Your Data?

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

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!