Why is this code not going into an infinite loop as suggested by JSR133?What is reflection and why is it useful?What is a serialVersionUID and why should I use it?How do I break out of nested loops in Java?Why is subtracting these two times (in 1927) giving a strange result?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?Why is char[] preferred over String for passwords?Why is it faster to process a sorted array than an unsorted array?Why does this code using random strings print “hello world”?Why is printing “B” dramatically slower than printing “#”?Why is executing Java code in comments with certain Unicode characters allowed?
Can't connect to Internet in bash using Mac OS
Intuition behind eigenvalues of an adjacency matrix
Strange math syntax in old basic listing
Expenditure in Poland - Forex doesn't have Zloty
Where can I find the list of all tendons in the human body?
How do I subvert the tropes of a train heist?
Can a wire having a 610-670 THz (frequency of blue light) AC frequency supply, generate blue light?
Yandex programming contest: Alarms
Do you play the upbeat when beginning to play a series of notes, and then after?
Can a helicopter mask itself from Radar?
Term for checking piece whose opponent daren't capture it
What kind of appearance can I expect if I both overexpose and push film?
Socratic Paradox
Is floating in space similar to falling under gravity?
60s (or earlier) short story where each colony has one person who doesn't connect well with others who is there for being able to absorb knowledge
Differences between “pas vrai ?”, “c’est ça ?”, “hein ?”, and “n’est-ce pas ?”
Modern approach to radio buttons
Uncommanded roll at high speed
Why would Lupin kill Pettigrew?
What does it mean when you think without speaking?
Select row of data if next row contains zero
Looking after a wayward brother in mother's will
Can you move on your turn, and then use the Ready Action to move again on another creature's turn?
What was this black-and-white film set in the Arctic or Antarctic where the monster/alien gets fried in the end?
Why is this code not going into an infinite loop as suggested by JSR133?
What is reflection and why is it useful?What is a serialVersionUID and why should I use it?How do I break out of nested loops in Java?Why is subtracting these two times (in 1927) giving a strange result?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?Why is char[] preferred over String for passwords?Why is it faster to process a sorted array than an unsorted array?Why does this code using random strings print “hello world”?Why is printing “B” dramatically slower than printing “#”?Why is executing Java code in comments with certain Unicode characters allowed?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
In JSR-133 section 3.1, which discusses the visibility of actions between threads - it is mentioned that the code example below, which does not utilise the volatile keyword for the boolean field, can become an infinite loop if two threads are running it. Here is the code from the JSR:
class LoopMayNeverEnd
boolean done = false;
void work()
while (!done)
// do work
void stopWork()
done = true;
Here is a quote of the important bit in that section that I'm interested in:
... Now imagine that two threads are created, and that one
thread calls work(), and at some point, the other thread calls stopWork(). Because there is
no happens-before relationship between the two threads, the thread in the loop may never
see the update to done performed by the other thread ...
And here is my own Java code I wrote just so I can see it loop:
public class VolatileTest
private boolean done = false;
public static void main(String[] args)
VolatileTest volatileTest = new VolatileTest();
volatileTest.runTest();
private void runTest()
Thread t1 = new Thread(() -> work());
Thread t2 = new Thread(() -> stopWork());
t1.start();
t2.start();
private void stopWork()
done = true;
System.out.println("stopped work");
private void work()
while(!done)
System.out.println("started work");
Although the results from consecutive executions are different - as expected - I don't see it ever going into an infinite loop. I'm trying to understand how I can simulate the infinite loop that the documentation suggests, what am I missing? How does declaring the boolean volatile, remove the infinite loop?
java multithreading concurrency volatile java-memory-model
|
show 5 more comments
In JSR-133 section 3.1, which discusses the visibility of actions between threads - it is mentioned that the code example below, which does not utilise the volatile keyword for the boolean field, can become an infinite loop if two threads are running it. Here is the code from the JSR:
class LoopMayNeverEnd
boolean done = false;
void work()
while (!done)
// do work
void stopWork()
done = true;
Here is a quote of the important bit in that section that I'm interested in:
... Now imagine that two threads are created, and that one
thread calls work(), and at some point, the other thread calls stopWork(). Because there is
no happens-before relationship between the two threads, the thread in the loop may never
see the update to done performed by the other thread ...
And here is my own Java code I wrote just so I can see it loop:
public class VolatileTest
private boolean done = false;
public static void main(String[] args)
VolatileTest volatileTest = new VolatileTest();
volatileTest.runTest();
private void runTest()
Thread t1 = new Thread(() -> work());
Thread t2 = new Thread(() -> stopWork());
t1.start();
t2.start();
private void stopWork()
done = true;
System.out.println("stopped work");
private void work()
while(!done)
System.out.println("started work");
Although the results from consecutive executions are different - as expected - I don't see it ever going into an infinite loop. I'm trying to understand how I can simulate the infinite loop that the documentation suggests, what am I missing? How does declaring the boolean volatile, remove the infinite loop?
java multithreading concurrency volatile java-memory-model
3
Remove your println statements, and you'll probably have a program that never stops. But even if you don't, remember that just because something can happen, even once in a million times, doesn't mean that it will always happen. It can depend on your JVM, your OS, etc. You just don't have any guarantee that the thread will see the new boolean value. Which is very different from saying "you are guaranteed that the thread won't see it".
– JB Nizet
Mar 24 at 10:08
Thanks for your comment. Removing the print statement in the while loop is enough to get it into an infinite loop... Now the program prints "stopped work" and then never ends. Where did the assignment to the boolean variable to true go?
– drewdles
Mar 24 at 10:13
1
It went to the register, or memory cache of the CPU core used by the stopping thread, or even to the main memory. But the reading thread can continue to read it from its own CPU core memory cache, because the field is not marked as volatile.
– JB Nizet
Mar 24 at 10:16
That makes sense. Final question, does declaring the boolean a volatile mean that stopWork() is always called first due to the happens-before relationship?
– drewdles
Mar 24 at 10:24
1
No, not at all. It guarantees that if a thread has written a value to the volatile field, then another thread reading the vaue of the volatile field will see the written value, and not some previous value.
– JB Nizet
Mar 24 at 10:26
|
show 5 more comments
In JSR-133 section 3.1, which discusses the visibility of actions between threads - it is mentioned that the code example below, which does not utilise the volatile keyword for the boolean field, can become an infinite loop if two threads are running it. Here is the code from the JSR:
class LoopMayNeverEnd
boolean done = false;
void work()
while (!done)
// do work
void stopWork()
done = true;
Here is a quote of the important bit in that section that I'm interested in:
... Now imagine that two threads are created, and that one
thread calls work(), and at some point, the other thread calls stopWork(). Because there is
no happens-before relationship between the two threads, the thread in the loop may never
see the update to done performed by the other thread ...
And here is my own Java code I wrote just so I can see it loop:
public class VolatileTest
private boolean done = false;
public static void main(String[] args)
VolatileTest volatileTest = new VolatileTest();
volatileTest.runTest();
private void runTest()
Thread t1 = new Thread(() -> work());
Thread t2 = new Thread(() -> stopWork());
t1.start();
t2.start();
private void stopWork()
done = true;
System.out.println("stopped work");
private void work()
while(!done)
System.out.println("started work");
Although the results from consecutive executions are different - as expected - I don't see it ever going into an infinite loop. I'm trying to understand how I can simulate the infinite loop that the documentation suggests, what am I missing? How does declaring the boolean volatile, remove the infinite loop?
java multithreading concurrency volatile java-memory-model
In JSR-133 section 3.1, which discusses the visibility of actions between threads - it is mentioned that the code example below, which does not utilise the volatile keyword for the boolean field, can become an infinite loop if two threads are running it. Here is the code from the JSR:
class LoopMayNeverEnd
boolean done = false;
void work()
while (!done)
// do work
void stopWork()
done = true;
Here is a quote of the important bit in that section that I'm interested in:
... Now imagine that two threads are created, and that one
thread calls work(), and at some point, the other thread calls stopWork(). Because there is
no happens-before relationship between the two threads, the thread in the loop may never
see the update to done performed by the other thread ...
And here is my own Java code I wrote just so I can see it loop:
public class VolatileTest
private boolean done = false;
public static void main(String[] args)
VolatileTest volatileTest = new VolatileTest();
volatileTest.runTest();
private void runTest()
Thread t1 = new Thread(() -> work());
Thread t2 = new Thread(() -> stopWork());
t1.start();
t2.start();
private void stopWork()
done = true;
System.out.println("stopped work");
private void work()
while(!done)
System.out.println("started work");
Although the results from consecutive executions are different - as expected - I don't see it ever going into an infinite loop. I'm trying to understand how I can simulate the infinite loop that the documentation suggests, what am I missing? How does declaring the boolean volatile, remove the infinite loop?
java multithreading concurrency volatile java-memory-model
java multithreading concurrency volatile java-memory-model
asked Mar 24 at 10:04
drewdlesdrewdles
209110
209110
3
Remove your println statements, and you'll probably have a program that never stops. But even if you don't, remember that just because something can happen, even once in a million times, doesn't mean that it will always happen. It can depend on your JVM, your OS, etc. You just don't have any guarantee that the thread will see the new boolean value. Which is very different from saying "you are guaranteed that the thread won't see it".
– JB Nizet
Mar 24 at 10:08
Thanks for your comment. Removing the print statement in the while loop is enough to get it into an infinite loop... Now the program prints "stopped work" and then never ends. Where did the assignment to the boolean variable to true go?
– drewdles
Mar 24 at 10:13
1
It went to the register, or memory cache of the CPU core used by the stopping thread, or even to the main memory. But the reading thread can continue to read it from its own CPU core memory cache, because the field is not marked as volatile.
– JB Nizet
Mar 24 at 10:16
That makes sense. Final question, does declaring the boolean a volatile mean that stopWork() is always called first due to the happens-before relationship?
– drewdles
Mar 24 at 10:24
1
No, not at all. It guarantees that if a thread has written a value to the volatile field, then another thread reading the vaue of the volatile field will see the written value, and not some previous value.
– JB Nizet
Mar 24 at 10:26
|
show 5 more comments
3
Remove your println statements, and you'll probably have a program that never stops. But even if you don't, remember that just because something can happen, even once in a million times, doesn't mean that it will always happen. It can depend on your JVM, your OS, etc. You just don't have any guarantee that the thread will see the new boolean value. Which is very different from saying "you are guaranteed that the thread won't see it".
– JB Nizet
Mar 24 at 10:08
Thanks for your comment. Removing the print statement in the while loop is enough to get it into an infinite loop... Now the program prints "stopped work" and then never ends. Where did the assignment to the boolean variable to true go?
– drewdles
Mar 24 at 10:13
1
It went to the register, or memory cache of the CPU core used by the stopping thread, or even to the main memory. But the reading thread can continue to read it from its own CPU core memory cache, because the field is not marked as volatile.
– JB Nizet
Mar 24 at 10:16
That makes sense. Final question, does declaring the boolean a volatile mean that stopWork() is always called first due to the happens-before relationship?
– drewdles
Mar 24 at 10:24
1
No, not at all. It guarantees that if a thread has written a value to the volatile field, then another thread reading the vaue of the volatile field will see the written value, and not some previous value.
– JB Nizet
Mar 24 at 10:26
3
3
Remove your println statements, and you'll probably have a program that never stops. But even if you don't, remember that just because something can happen, even once in a million times, doesn't mean that it will always happen. It can depend on your JVM, your OS, etc. You just don't have any guarantee that the thread will see the new boolean value. Which is very different from saying "you are guaranteed that the thread won't see it".
– JB Nizet
Mar 24 at 10:08
Remove your println statements, and you'll probably have a program that never stops. But even if you don't, remember that just because something can happen, even once in a million times, doesn't mean that it will always happen. It can depend on your JVM, your OS, etc. You just don't have any guarantee that the thread will see the new boolean value. Which is very different from saying "you are guaranteed that the thread won't see it".
– JB Nizet
Mar 24 at 10:08
Thanks for your comment. Removing the print statement in the while loop is enough to get it into an infinite loop... Now the program prints "stopped work" and then never ends. Where did the assignment to the boolean variable to true go?
– drewdles
Mar 24 at 10:13
Thanks for your comment. Removing the print statement in the while loop is enough to get it into an infinite loop... Now the program prints "stopped work" and then never ends. Where did the assignment to the boolean variable to true go?
– drewdles
Mar 24 at 10:13
1
1
It went to the register, or memory cache of the CPU core used by the stopping thread, or even to the main memory. But the reading thread can continue to read it from its own CPU core memory cache, because the field is not marked as volatile.
– JB Nizet
Mar 24 at 10:16
It went to the register, or memory cache of the CPU core used by the stopping thread, or even to the main memory. But the reading thread can continue to read it from its own CPU core memory cache, because the field is not marked as volatile.
– JB Nizet
Mar 24 at 10:16
That makes sense. Final question, does declaring the boolean a volatile mean that stopWork() is always called first due to the happens-before relationship?
– drewdles
Mar 24 at 10:24
That makes sense. Final question, does declaring the boolean a volatile mean that stopWork() is always called first due to the happens-before relationship?
– drewdles
Mar 24 at 10:24
1
1
No, not at all. It guarantees that if a thread has written a value to the volatile field, then another thread reading the vaue of the volatile field will see the written value, and not some previous value.
– JB Nizet
Mar 24 at 10:26
No, not at all. It guarantees that if a thread has written a value to the volatile field, then another thread reading the vaue of the volatile field will see the written value, and not some previous value.
– JB Nizet
Mar 24 at 10:26
|
show 5 more comments
1 Answer
1
active
oldest
votes
The actual behavior is OS and JVM specific. For example, by default, Java runs in client mode on 32-bit Windows and in server mode on the Mac. In client mode the work
method will terminate, but will not terminate in server mode.
This happens because of the Java server JIT compiler optimization. The JIT compiler may optimize the while loop, because it does not see the variable done
changing within the context of the thread. Another reason of the infinite loop might be because one thread may end up reading the value of the flag from its registers or cache instead of going to memory. As a result, it may never see the change made by the another thread to this flag.
Essentially by adding volatile
you make the thread owning done
flag to not cache this flag. Thus, the boolean
value is stored in common memory and therefore guarantees visibility. Also, by using volatile
you disabling JIT optimization that can inline the flag value.
Basically if you want to reproduce infinite loop - just run your program in server mode:
java -server VolatileTest
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
add a comment |
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%2f55322624%2fwhy-is-this-code-not-going-into-an-infinite-loop-as-suggested-by-jsr133%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The actual behavior is OS and JVM specific. For example, by default, Java runs in client mode on 32-bit Windows and in server mode on the Mac. In client mode the work
method will terminate, but will not terminate in server mode.
This happens because of the Java server JIT compiler optimization. The JIT compiler may optimize the while loop, because it does not see the variable done
changing within the context of the thread. Another reason of the infinite loop might be because one thread may end up reading the value of the flag from its registers or cache instead of going to memory. As a result, it may never see the change made by the another thread to this flag.
Essentially by adding volatile
you make the thread owning done
flag to not cache this flag. Thus, the boolean
value is stored in common memory and therefore guarantees visibility. Also, by using volatile
you disabling JIT optimization that can inline the flag value.
Basically if you want to reproduce infinite loop - just run your program in server mode:
java -server VolatileTest
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
add a comment |
The actual behavior is OS and JVM specific. For example, by default, Java runs in client mode on 32-bit Windows and in server mode on the Mac. In client mode the work
method will terminate, but will not terminate in server mode.
This happens because of the Java server JIT compiler optimization. The JIT compiler may optimize the while loop, because it does not see the variable done
changing within the context of the thread. Another reason of the infinite loop might be because one thread may end up reading the value of the flag from its registers or cache instead of going to memory. As a result, it may never see the change made by the another thread to this flag.
Essentially by adding volatile
you make the thread owning done
flag to not cache this flag. Thus, the boolean
value is stored in common memory and therefore guarantees visibility. Also, by using volatile
you disabling JIT optimization that can inline the flag value.
Basically if you want to reproduce infinite loop - just run your program in server mode:
java -server VolatileTest
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
add a comment |
The actual behavior is OS and JVM specific. For example, by default, Java runs in client mode on 32-bit Windows and in server mode on the Mac. In client mode the work
method will terminate, but will not terminate in server mode.
This happens because of the Java server JIT compiler optimization. The JIT compiler may optimize the while loop, because it does not see the variable done
changing within the context of the thread. Another reason of the infinite loop might be because one thread may end up reading the value of the flag from its registers or cache instead of going to memory. As a result, it may never see the change made by the another thread to this flag.
Essentially by adding volatile
you make the thread owning done
flag to not cache this flag. Thus, the boolean
value is stored in common memory and therefore guarantees visibility. Also, by using volatile
you disabling JIT optimization that can inline the flag value.
Basically if you want to reproduce infinite loop - just run your program in server mode:
java -server VolatileTest
The actual behavior is OS and JVM specific. For example, by default, Java runs in client mode on 32-bit Windows and in server mode on the Mac. In client mode the work
method will terminate, but will not terminate in server mode.
This happens because of the Java server JIT compiler optimization. The JIT compiler may optimize the while loop, because it does not see the variable done
changing within the context of the thread. Another reason of the infinite loop might be because one thread may end up reading the value of the flag from its registers or cache instead of going to memory. As a result, it may never see the change made by the another thread to this flag.
Essentially by adding volatile
you make the thread owning done
flag to not cache this flag. Thus, the boolean
value is stored in common memory and therefore guarantees visibility. Also, by using volatile
you disabling JIT optimization that can inline the flag value.
Basically if you want to reproduce infinite loop - just run your program in server mode:
java -server VolatileTest
edited Mar 24 at 19:52
answered Mar 24 at 19:32
ZgurskyiZgurskyi
1,384179
1,384179
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
add a comment |
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
Adding -server as a vm argument didn't create an infinite loop
– drewdles
Mar 27 at 12:56
add a comment |
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%2f55322624%2fwhy-is-this-code-not-going-into-an-infinite-loop-as-suggested-by-jsr133%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
3
Remove your println statements, and you'll probably have a program that never stops. But even if you don't, remember that just because something can happen, even once in a million times, doesn't mean that it will always happen. It can depend on your JVM, your OS, etc. You just don't have any guarantee that the thread will see the new boolean value. Which is very different from saying "you are guaranteed that the thread won't see it".
– JB Nizet
Mar 24 at 10:08
Thanks for your comment. Removing the print statement in the while loop is enough to get it into an infinite loop... Now the program prints "stopped work" and then never ends. Where did the assignment to the boolean variable to true go?
– drewdles
Mar 24 at 10:13
1
It went to the register, or memory cache of the CPU core used by the stopping thread, or even to the main memory. But the reading thread can continue to read it from its own CPU core memory cache, because the field is not marked as volatile.
– JB Nizet
Mar 24 at 10:16
That makes sense. Final question, does declaring the boolean a volatile mean that stopWork() is always called first due to the happens-before relationship?
– drewdles
Mar 24 at 10:24
1
No, not at all. It guarantees that if a thread has written a value to the volatile field, then another thread reading the vaue of the volatile field will see the written value, and not some previous value.
– JB Nizet
Mar 24 at 10:26