CompletableFuture and Happens-before Order
I intend to create 2 threads to do some computation then checking (each of them) whether the other also completed its computation otherwise simply exit. When thread1 finds out that the other (thread2) also completed its computation then thread1 should continue with an additional computation based on the result of thread2 (otherwise would simply exit).
So I intend to use the Runnable
below with 2 threads like this:
me = new CompletableFuture<>();
theOther = new CompletableFuture<>();
executorService.submit(createWorker(data, true, me, theOther));
executorService.submit(createWorker(data++, false, theOther, me));
and the Runnable
is created this way:
private Runnable createWorker(int data, boolean callRegion1,
CompletableFuture<Payment> me,
CompletableFuture<Payment> theOther) {
return () -> {
Payment myPayment;
try {
myPayment = postData(data, callRegion1);
me.complete(myPayment);
} catch (Throwable ex) {
me.completeExceptionally(ex);
// comparison with theOther no longer make sense
return;
}
// skip comparison when myPayment is null
if (myPayment == null) {
log.error("myPayment == null for data = {}", data);
return;
}
// get otherPayment and ignore exceptions
Payment otherPayment = theOther.getNow(absentPayment);
// skip comparison when otherPayment is null or not yet available
if (otherPayment == null || otherPayment == absentPayment) {
return;
}
// doing the comparison here
if (otherPayment.getData() + myPayment.getData() != 0) {
log.error("M/M or M/SM for data = {}", data);
System.exit(-1);
}
};
}
The created Runnable
is not explicitly synchronized so I fear that the code below:
theOther.getNow(absentPayment);
might be evaluated to absentPayment
the same time by both threads which would be bad for me (let's name this the bad scenario).
Q: Is the bad scenario possible and why? if not possible, again why not?
java jls happens-before
add a comment |
I intend to create 2 threads to do some computation then checking (each of them) whether the other also completed its computation otherwise simply exit. When thread1 finds out that the other (thread2) also completed its computation then thread1 should continue with an additional computation based on the result of thread2 (otherwise would simply exit).
So I intend to use the Runnable
below with 2 threads like this:
me = new CompletableFuture<>();
theOther = new CompletableFuture<>();
executorService.submit(createWorker(data, true, me, theOther));
executorService.submit(createWorker(data++, false, theOther, me));
and the Runnable
is created this way:
private Runnable createWorker(int data, boolean callRegion1,
CompletableFuture<Payment> me,
CompletableFuture<Payment> theOther) {
return () -> {
Payment myPayment;
try {
myPayment = postData(data, callRegion1);
me.complete(myPayment);
} catch (Throwable ex) {
me.completeExceptionally(ex);
// comparison with theOther no longer make sense
return;
}
// skip comparison when myPayment is null
if (myPayment == null) {
log.error("myPayment == null for data = {}", data);
return;
}
// get otherPayment and ignore exceptions
Payment otherPayment = theOther.getNow(absentPayment);
// skip comparison when otherPayment is null or not yet available
if (otherPayment == null || otherPayment == absentPayment) {
return;
}
// doing the comparison here
if (otherPayment.getData() + myPayment.getData() != 0) {
log.error("M/M or M/SM for data = {}", data);
System.exit(-1);
}
};
}
The created Runnable
is not explicitly synchronized so I fear that the code below:
theOther.getNow(absentPayment);
might be evaluated to absentPayment
the same time by both threads which would be bad for me (let's name this the bad scenario).
Q: Is the bad scenario possible and why? if not possible, again why not?
java jls happens-before
add a comment |
I intend to create 2 threads to do some computation then checking (each of them) whether the other also completed its computation otherwise simply exit. When thread1 finds out that the other (thread2) also completed its computation then thread1 should continue with an additional computation based on the result of thread2 (otherwise would simply exit).
So I intend to use the Runnable
below with 2 threads like this:
me = new CompletableFuture<>();
theOther = new CompletableFuture<>();
executorService.submit(createWorker(data, true, me, theOther));
executorService.submit(createWorker(data++, false, theOther, me));
and the Runnable
is created this way:
private Runnable createWorker(int data, boolean callRegion1,
CompletableFuture<Payment> me,
CompletableFuture<Payment> theOther) {
return () -> {
Payment myPayment;
try {
myPayment = postData(data, callRegion1);
me.complete(myPayment);
} catch (Throwable ex) {
me.completeExceptionally(ex);
// comparison with theOther no longer make sense
return;
}
// skip comparison when myPayment is null
if (myPayment == null) {
log.error("myPayment == null for data = {}", data);
return;
}
// get otherPayment and ignore exceptions
Payment otherPayment = theOther.getNow(absentPayment);
// skip comparison when otherPayment is null or not yet available
if (otherPayment == null || otherPayment == absentPayment) {
return;
}
// doing the comparison here
if (otherPayment.getData() + myPayment.getData() != 0) {
log.error("M/M or M/SM for data = {}", data);
System.exit(-1);
}
};
}
The created Runnable
is not explicitly synchronized so I fear that the code below:
theOther.getNow(absentPayment);
might be evaluated to absentPayment
the same time by both threads which would be bad for me (let's name this the bad scenario).
Q: Is the bad scenario possible and why? if not possible, again why not?
java jls happens-before
I intend to create 2 threads to do some computation then checking (each of them) whether the other also completed its computation otherwise simply exit. When thread1 finds out that the other (thread2) also completed its computation then thread1 should continue with an additional computation based on the result of thread2 (otherwise would simply exit).
So I intend to use the Runnable
below with 2 threads like this:
me = new CompletableFuture<>();
theOther = new CompletableFuture<>();
executorService.submit(createWorker(data, true, me, theOther));
executorService.submit(createWorker(data++, false, theOther, me));
and the Runnable
is created this way:
private Runnable createWorker(int data, boolean callRegion1,
CompletableFuture<Payment> me,
CompletableFuture<Payment> theOther) {
return () -> {
Payment myPayment;
try {
myPayment = postData(data, callRegion1);
me.complete(myPayment);
} catch (Throwable ex) {
me.completeExceptionally(ex);
// comparison with theOther no longer make sense
return;
}
// skip comparison when myPayment is null
if (myPayment == null) {
log.error("myPayment == null for data = {}", data);
return;
}
// get otherPayment and ignore exceptions
Payment otherPayment = theOther.getNow(absentPayment);
// skip comparison when otherPayment is null or not yet available
if (otherPayment == null || otherPayment == absentPayment) {
return;
}
// doing the comparison here
if (otherPayment.getData() + myPayment.getData() != 0) {
log.error("M/M or M/SM for data = {}", data);
System.exit(-1);
}
};
}
The created Runnable
is not explicitly synchronized so I fear that the code below:
theOther.getNow(absentPayment);
might be evaluated to absentPayment
the same time by both threads which would be bad for me (let's name this the bad scenario).
Q: Is the bad scenario possible and why? if not possible, again why not?
java jls happens-before
java jls happens-before
edited Dec 29 '18 at 0:16
adrhc
asked Dec 28 '18 at 23:43
adrhcadrhc
445314
445314
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965476%2fcompletablefuture-and-happens-before-order%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965476%2fcompletablefuture-and-happens-before-order%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown