Are synchronizes-with edegs compiler re-ordering barriers in both directions?
Asked Answered
W

1

10

I have a question regarding the Java Memory Model. Given the following example:

action 1
action 2
synchronized(monitorObject) { //acquire
    action 3
} //release
action 4

acquire and release can be any synchronizes-with edge (lock, unlock, start thread, join thread, detect thread interruption, volatile-write, volatile-read, etc.)

Is it guaranteed that action 3 can't be moved before the acquire and can't be moved after the release?

And is it guaranteed that action 2 can't be moved after the acquire (neither before nor after the release) and that action 4 can't be moved before the release (neither before nor after the acquire)?

So are synchronizes-with edges "bidirectional barriers" for the compiler's re-ordering actions?


EDIT 1 I am concerned about this because if synchronizes-with edges were not bidirectional re-ordering barriers, the compiler could simply create a deadlock by moving lock acquires into others.

Or are bidirectional re-ordering barriers not even necessary to prevent this because lock acquires can't be pushed into others because that would change the synchronization order?


EDIT 2 The actions 1, 2, 3 and 4 are "inter-thread actions" as defined by the JMM.


EDIT 3 Here's an example that shows how reordering might cause a deadlock:

x and y are shared variables and syncA and syncB may be acquired by any other thread. But with the following code, there is no deadlock possible.

/* 1 */  synchronized(syncA) {
/* 2 */      x = 1;
/* 3 */  }
/* 4 */  y = 0;
/* 5 */  synchronized(syncB) {
/* 6 */      y = 1;
/* 7 */  }

If, however, the acquire of syncA is reordered into the syncB block this might cause a deadlock:

y = 0;
synchronized(syncB) {
    y = 1;
    synchronized(syncA) {
        x = 1;
    }
}

I think this is not a legal compiler transformation, because it would change the synchronization order. Am I right with this assumption? What part of the Java Memory Model (JMM) allows/disallows this?

Whirligig answered 3/11, 2014 at 22:27 Comment(18)
"action" is a tricky word here. If the "actions" are method calls with observable effects, I'm reasonably certain 1, 2, 3, and 4 must be executed in that order with or without the synchronized block being there. Otherwise, chaos.Stannite
I don't know about action 3, I think it must occur inside the block but i'm not sure. Action 2 can be moved after the acquire or action 3, for sure. Action 4 can't be reordered given what you have there. It has to occur after the release.Hobson
@markspace: "Action 2 can be moved after the acquire or action 3, for sure." Huh? You're saying if I do System.out.println("1"); then System.out.println("2"); in a synchronized block, I could see 2 then 1? Citation? (Or perhaps a better example wouldn't deal with console I/O, but you can follow the question.)Stannite
Please consider the edits on the question.Whirligig
@MinecraftShamrock: The question as it stands is pretty vague. A concrete example might help.Stannite
@Whirligig With your edits, I think you should ask the question again. Show where you think the compiler might "create deadlock" by "moving lock acquires." I'm starting to smell XY problems here.Hobson
@T.J.Crowder The compiler/system can reorder writes. Action 1 2 and 3 can occur in any order, as long as they happen before the release. Action 4 must occur after the release (but we don't know when, just "after").Hobson
@markspace: It can do some limited reordering. A blanket statement "2 could be before 3, sure" is so inaccurate as to be not useful. (Agreed on the X/Y problem thing.)Stannite
@T.J.Crowder But if it can do any reordering at all then you have to answer "yes" when someone asks if it can be reordered. It's the general case. (And I said 2 could happen after 3, not before.)Hobson
@markspace: Without qualification, explanation, or citation with that explanation? No. No, you don't. And doing so is not useful. Anyway, I think we're all clear on what we mean. Best,Stannite
@T.J.Crowder action 1 and 2 can definitely be moved into the synchronized block.Brendin
@Brendin what about edit 3?Whirligig
@Whirligig I am pretty sure that the reordering in EDIT 3 is not allowed because it would break the happens-before relationship transitivity.Brendin
@Brendin Do you mean because hb(1, 3), hb(3, 5) and hb(5, 7) and cause in the reordered transformation hb(1, 5) is not the case?Whirligig
Sort of - hb applies to actions in threads, say T1 and T2, so you have (1) program order that implies HB(T1-1, T1-3), hb(T1-3, T1-5) etc. + same for T2 and (2) inter thread order due to the synchronised block: if T1 acquires the monitor in (1) before T2 then hb(T1-3, T2-1) then you need to reason about the second block (either T1 or T2 can gat the lock first). And if you assume your reordering it will probably create an inconsistency (can't look in details now).Brendin
@Brendin I think I understand now. If you post an answer I can accept it to give you some reputation :)Whirligig
@Brendin So generally the order in which synchronization actions happen must not be changes by the compiler and and Statements before a lock release and volatile read or write must not be moved after it. Right?Whirligig
yes - this is related: #19216448 - and the link to the cookbook has your answerBrendin
W
2

Thanks to assylias for linking to this question which contains an answer with this image from the JSR-133 Cookbook:

Reordering Rules Table

According to this image the compiler transformation from EDIT 3 is illegal, because it reorders two MonitorEnters.

Also, this table shows which synchronization-edges are what kinds of "reordering-barriers" for which other operations.

Thank you for your help :)

Whirligig answered 6/11, 2014 at 18:26 Comment(3)
@JohnVint It would be great if you could explain whitch two lines in edit 3 would actually be reordered. Thank you for pointing this out :)Whirligig
As I tried to write the example I noticed you had syncB before syncA so your answer is absolutely correct! My response was in the case syncB was inside syncA which is the argument you didnt make, sorry!Spruik
@JohnVint Lol xD Still thank you for having a critical look on the question.Whirligig

© 2022 - 2024 — McMap. All rights reserved.