How does Java make assignments atomic?

G

graftonfot

From what I understand, Java guarantees that all assignments to
primitive types (except non-volatile 64-bit types) will be atomic.

How does it do this? I thought that the only truly uninterruptable
processor instruction was the test-and-set, and that test-and-set was
the basis from which richer thread synchronization resources typically
provided by an underlying operating system (e.g. semaphores, mutexes,
critical sections) were built.

Does Java internally implement all of its generated assignment opcodes
inside some kind of test-and-set-based wrappers?

Thanks.
 
O

Oliver Wong

primitive types (except non-volatile 64-bit types) will be atomic.

How does it do this? I thought that the only truly uninterruptable
processor instruction was the test-and-set, and that test-and-set was
the basis from which richer thread synchronization resources typically
provided by an underlying operating system (e.g. semaphores, mutexes,
critical sections) were built.

Does Java internally implement all of its generated assignment opcodes
inside some kind of test-and-set-based wrappers?

I think you are confusing several concepts here. First of all, for every
single processor design I've encountered, none of the CPU instructions are
"interruptable". Jump instructions, for example, are not interruptable, nor
are ADD instructions, nor copying a value from one register to another.

In multiple processor designs, the individual processors don't
"interrupt" each other either. What may pose problems is that they may have
their own caches and have stale data if their caches do not accurately
reflect what is in RAM.

It is not correct to say that Java "implements" anything. There is a
Java Language Specification, and there is a Java Platform Specification. The
specifications guarantee that all assignments on primitive types (with the
exception noted above) are atomic. How that is accomplished is actually up
to the implementor of the Java Platform.

Note though that there is no "Test And Set" bytecode instruction that I
am aware of. Rather, the class files will contain normal "assignment"
operators, which an interpreter or JIT compiler will have to translate into
instructions which the CPU can understand.

If these instructions are storing primitive types whose size matches the
wordsize of the architecture (e.g. ints on a 32 bit architecture), then I
believe the "storage" instruction at the CPU level should already be atomic,
so nothing special needs to be done. It's only when the wordsize is smaller
than the java primitive size (e.g. java longs on 32 bit architecture, or
java ints on 16 bit architecture), then typically the storing will need to
be done in two or more instructions. Then something special needs to happen.

- Oliver
 
R

Roedy Green

primitive types (except non-volatile 64-bit types) will be atomic.

How does it do this?

Bruce Eckel is puzzled too:
http://www.artima.com/weblogs/viewpost.jsp?thread=126834

The atomicity of 32 bit operations is easy on a Pentium. The CPU does
a store in a single cycle for 8, 16, 32 bits.

The atomicity of 64 bit ops is a problem, since the save needs two mov
mem,reg instructions in a row without interruption and without another
thread intervening at that locatation.
 
G

graftonfot

Let's limit the discussion to single processors for the time being.
And, yes, OK, I wasn't 100% precise with my terminology, but from a
practical perspective, I'd bet most people knew what I meant. So I
could have said "any Java implementation that conforms to the JLS
should guarantee that these assignments are atomic..." or something
similar.

I'd agree (not that you asked me to) that single CPU instructions are
probably not interruptable. But when the JLS states that, say, an
integer assignment statement is guaranteed to be atomic, what does that
cover? Which of the following are "assignment" statements for
instance?

i = 4;
i = j;
i = j + k;
i = 3 * x * y / z;

Which of these will be atomic? And will the simplest one (perhaps the
first?) end up being implemented as a sequence of CPU instructions? If
so, what does the Java implementation do to guarantee that that
possibly-interruptable sequence of machine instructions will not in
fact be interrupted? That was the intended crux of my question.
Thanks.
 
S

Scott W Gifford

(e-mail address removed) writes:

[...]
when the JLS states that, say, an
integer assignment statement is guaranteed to be atomic, what does that
cover? Which of the following are "assignment" statements for
instance?

i = 4;
i = j;
i = j + k;
i = 3 * x * y / z;

They are all assignment statements.
Which of these will be atomic?

Speaking in general (I don't know Java's implementation details), all
of the calculations on the right-hand side of the expression will be
done at once, then stored atomically into the variable on the
left-hand side. For example, in psuedoassembly, "i = j + k" might be:

MOV [j] -> ax
ADD [k] -> ax
MOV ax ->

where just the final MOV has to be atomic in order for the assignment
to be atomic.

Hope this helps,

-----Scott.
 
R

Roedy Green

i = 4;
i = j;
i = j + k;
i = 3 * x * y / z;

Which of these will be atomic? And will the simplest one (perhaps the
first?) end up being implemented as a sequence of CPU instructions? If
so, what does the Java implementation do to guarantee that that
possibly-interruptable sequence of machine instructions will not in
fact be interrupted? That was the intended crux of my question.
Thanks.

As someone with an assembler background, it would never occur that was
what you meant. If you want great hunks of code to run without
interference like that you must protect the code and the variables in
synchronized blocks.

The other thing to realise that variables typically have two homes, a
register and a ram location. The register caches the ram value. Other
threads will see the ram value and may have their own register caches.
If you want other threads to see the latest value you must get the
register value saved back before you let other threads peek. Volatile
inhibits register caching, but just the same, all arithmetic has to go
on in registers, so unless you have use synchronized, you will always
see slightly out of date values.
 
R

Roedy Green

calculations on the right-hand side of the expression will be
done at once, then stored atomically into the variable on the
left-hand side. For example, in psuedoassembly, "i = j + k" might be:

MOV [j] -> ax
ADD [k] -> ax
MOV ax ->

where just the final MOV has to be atomic in order for the assignment
to be atomic.


but the expression calculation is NOT done "at once", but in steps.
Other threads could be meddling with the values of j and k at any
point if you don't take special precautions. you might get the old or
new value of j and k.

What is worse is the the actual code would likely look more like this

// ax contains j at this point
// bx contains k at his point
add ax,bx -> bx
// bx contains j + k at this point
mov bx -> i

So there is even more potential for a badly out of date j and k.
 
S

Scott W Gifford

Roedy Green said:
calculations on the right-hand side of the expression will be
done at once, then stored atomically into the variable on the
left-hand side. For example, in psuedoassembly, "i = j + k" might be:

MOV [j] -> ax
ADD [k] -> ax
MOV ax ->

where just the final MOV has to be atomic in order for the assignment
to be atomic.


but the expression calculation is NOT done "at once", but in steps.
Other threads could be meddling with the values of j and k at any
point if you don't take special precautions. you might get the old or
new value of j and k.


Right, absolutely, but the incorrect result will be stored atomically:
it will either have the old value, or the new (possibly incorrect)
value, never something that's half one and half the other.

At least that's true in general; not sure about how Java does this
specifically.

---ScottG.
 
O

Oliver Wong

I'd agree (not that you asked me to) that single CPU instructions are
probably not interruptable. But when the JLS states that, say, an
integer assignment statement is guaranteed to be atomic, what does that
cover? Which of the following are "assignment" statements for
instance?

i = 4;
i = j;
i = j + k;
i = 3 * x * y / z;

Which of these will be atomic? And will the simplest one (perhaps the
first?) end up being implemented as a sequence of CPU instructions? If
so, what does the Java implementation do to guarantee that that
possibly-interruptable sequence of machine instructions will not in
fact be interrupted? That was the intended crux of my question.
Thanks.

Only the action of assignment itself is atomic. So let me take the last
example, first; the one that says "i = 3 * x * y / z;" The evaluation of the
expression "3 * x * y / z" might not be atomic. But once that expression is
evaluated (let's say it ends up being equal to 12), then placing the value
of 12 into i is atomic. That is to say, it should be possible, in Java, for
you to see "12" partially in i because only the first 8 bits of the register
were set, and the 24 other bits are still random data.

Because CPU instructions are not interruptable, and the because storing
the value 12 into a register can be done in a single instruction, the
atomicity of the assignment happens "automagically" due to the way the x86
architecture is designed.

Now let's look at your second example, "i = j;" Again, ONLY the
assignment is atomic. So it's possible that between the evaluation of the
expression "j", and the storing of that value into "i", there is a thread
switching that occurs. So the processor might read the value of j, but then
a context switch occurs, and the value of j is updated, and then we switch
back to the first thread, and the old value of j is stored into i.

- Oliver
 
E

Eric Sosman

Oliver Wong wrote On 12/15/05 18:15,:
I think you are confusing several concepts here. First of all, for every
single processor design I've encountered, none of the CPU instructions are
"interruptable". Jump instructions, for example, are not interruptable, nor
are ADD instructions, nor copying a value from one register to another.

It's sort of beside the main point, but quite a few
processors provide interruptable instructions. Most that
I've encountered are of the "self-repeating" variety: they'll
do one operation, adjust a few registers, and keep on cycling
until a register goes to zero or something. These are usually
interruptible "between" the sub-operations; since the state
is recorded in the registers, upon resumption they just pick
up where they left off. String searches, memory moves --
heck, I've even used a processor that could do multiple I/O
operations this way.
In multiple processor designs, the individual processors don't
"interrupt" each other either. What may pose problems is that they may have
their own caches and have stale data if their caches do not accurately
reflect what is in RAM.

Again somewhat beside the point, but I've never seen an
MP machine (whether S or not) that didn't use CPU-to-CPU
interrupts in some form. It might be possible to build one,
but it's hard to imagine that the operation would be very
efficient. Without an inter-CPU signalling mechanism, just
booting the box in the first place seems pretty difficult.
It is not correct to say that Java "implements" anything. There is a
Java Language Specification, and there is a Java Platform Specification. The
specifications guarantee that all assignments on primitive types (with the
exception noted above) are atomic. How that is accomplished is actually up
to the implementor of the Java Platform.

... and now we're back on track, and the rest seems
reasonable. I might nit-pick about "architecture" versus
"implementation" here and there, but Oliver's main point
stands: the Java language and platform specify various
guarantees and requirements, and it's up to the Java
implementors to see that the requirements are met and the
guarantees upheld.
 
Joined
Oct 24, 2010
Messages
13
Reaction score
0
Good discussion guys , does guarantee of this atomicity remains with every java implementation ? also it only guarantee for variable up to 32 bit ? any logic behind that , does that any thing to do with 32 bit processor ?

What will happen if we run Java in 16 bit processor or 64 bit processor ?

Thanks
Javin
 

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,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top