Why is this unsafe for multithreading?

U

user8583

I am trying to understand if/why sharing a simple 'int' variable is unsafe in a multithreading context, under the assumption that only one thread writes on it, and the other threads only read it.

I understand that without further constrains the fact that other threads only read the int is a matter of blind confidence in the programmer. I also understand that there are atomic templates or interlocked operations that are widespread and easy to use. But nonetheless I would like to know if thereis something more fundamental about the unsafety of a shared 'int' that I quite don't get in this particular situation where only one thread is expected to modify the data.
 
A

Alf P. Steinbach

I am trying to understand if/why sharing a simple 'int' variable is unsafe in a multithreading context, under the assumption that only one thread writes on it, and the other threads only read it.

I understand that without further constrains the fact that other threads only read the int is a matter of blind confidence in the programmer. I also understand that there are atomic templates or interlocked operations that are widespread and easy to use. But nonetheless I would like to know if there is something more fundamental about the unsafety of a shared 'int' that I quite don't get in this particular situation where only one thread is expected to modify the data.

Don't post with Quoted Printable.
 
B

Bo Persson

I am trying to understand if/why sharing a simple 'int' variable is unsafe in a multithreading context, under the assumption that only one thread writes on it, and the other threads only read it.

I understand that without further constrains the fact that other threads only read the int is a matter of blind confidence in the programmer. I also understand that there are atomic templates or interlocked operations that are widespread and easy to use. But nonetheless I would like to know if there is something more fundamental about the unsafety of a shared 'int' that I quite don't get in this particular situation where only one thread is expected to modify the data.

Depending on your hardware, the other threads (cores) might not see the
updates, or not see the same value at the same time.



Bo Persson
 
K

K. Frank

Hello user and Bo!

[email protected] wrote 2012-07-08 21:09:

Depending on your hardware, the other threads (cores) might not see the
updates, or not see the same value at the same time.

Bo Persson

Furthermore, the reader threads may even see an inconsistent
or garbage value. Admittedly, this is more likely with a long
or a double than an int, but the language offers no guarantee.

Consider a four-byte int and hardware where bytes are written
one at a time. The writer thread might have written only one
of the four bytes when a reader thread reads the int. The
reader thread then gets one new byte and three old bytes,
neither the old value of the int nor the new.

I haven't seen this with ints, but I have seen it with doubles.

I had the misfortune one time of using an explicitly multi-
threaded third-part library that had a thread use unprotected
(neither atomic nor mutex-protected) writes to update some
doubles. Client code would then read those doubles. Every
once in a while you would get garbage (neither the old nor
the new value of the double), because only one four-byte word
of the eight-byte double had been written when the read occurred.

Note, without synchronization on the library side, there was
nothing that the client code could do to prevent this problem
(other than try to guess whether the value was bogus, and re-read
the double until it became "good").


Good luck.


K. Frank
 
J

Joshua Maurice

I am trying to understand if/why sharing a simple 'int' variable is unsafe
in a multithreading context, under the assumption that only one thread
writes on it, and the other threads only read it.

I understand that without further constrains the fact that other threads
only read the int is a matter of blind confidence in the programmer. I also
understand that there are atomic templates or interlocked operations that
are widespread and easy to use. But nonetheless I would like to know if
there is something more fundamental about the unsafety of a shared 'int'
that I quite don't get in this particular situation where only one thread
is expected to modify the data.

For real world uses AFAIK, here are potential problems.

1- Tearing. int might not be atomically updated, and thus you might
get "values out of thin air".

2- Lack of immediate updates. A wonderful example is:
int x;
//...
while (x)
do_something();
If the compiler can prove that do_something() does not write to b
(such as by inline expansion), then the compiler can transformation
that to:
int x;
//...
int tmp = x;
while (tmp)
do_something();
Rendering you dead in the water. There's an obscure rule in the C++11
standard that prevents this kind of transformation, but only for
atomic reads, not regular reads.

3- Everything I don't know about.
 
N

Nobody

I am trying to understand if/why sharing a simple 'int' variable is unsafe
in a multithreading context, under the assumption that only one thread
writes on it, and the other threads only read it.

Reading and writing an "int" are not *guaranteed* to be atomic operations.

On systems where the data bus is narrower than an int, it may require
multiple transfers, meaning that the reader may see a partially-modified
value.

On systems where the data bus is wider than an int, writing a single int
may require a read-modify-write cycle. If another CPU concurrently
writes to another int which is packed into the same word, one of the
writes may be lost.

The former is unlikely on typical systems (i.e. where an int is no larger
than a word, and is aligned to a word boundary). The latter was
specifically addressed in C++11, IIRC.
 
B

BGB

Ok. Name a single system still in use where the data bus is narrower than an int.

besides maybe some still lingering 8088 and 386SX systems?...


actually, for the most part, one can be lazy and just mark the variables
as 'volatile' and for the most part everything seems to work ok (at
least on x86 and x86-64 systems).
 
N

Nobody

Actually, modern AVR's are 32-bit.

"AVR32" is 32-bit, but Atmel still sell plenty of 8-bit AVRs. Microchip
sell 8, 16 and 32-bit PICs, 8051s and Z80s are still common.
Yet, I should have said name a single multicore processor with a data bus
narrower than an int given the orignal posting.

Single core or multi-core makes no difference. Simple time-slicing on a
single core is vulnerable to the same issue.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top