I am new to Java8 and multithreading work. I tried this piece of code below
public class Test {
public static boolean bchanged = true;
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
while (true) {
if (bchanged != bchanged) {
System.out.println("here");
}
}
}
}
).start();
new Thread((Runnable) () -> {
while (true) {
bchanged = !bchanged;
}
}).start();
}
}
when I was running this code, there is no print of "here". However, when I change
public static volatile boolean bchanged = true;
then the "here" will be printed out.
My original deduction was that, the lambda will have a local copy of the boolean value, and it won't affect the other thread when it is not volatile, but when I tried print out the boolean value in both threads, it proved I was wrong. So I am very confused in this case, how volatile affect the way lambda work.
This isn't about lambdas, this is about accessing a shared variable in multiple threads. You need to use synchronized, locks, AtomicBoolean, volatile, or some other thread-safety alternative. With the code you wrote the compiler is likely to cache the value of bchanged. It doesn't know that there's another thread modifying it, so the first thread sees a stale cached value.
As described in other answers, volatile and lambda has nothing to do together.
Volatile is printing "here" because the value of variable "bchanged" is not cached as "the volatile keyword in Java is used as an indicator to Java compiler and Thread that do not cache value of this variable and always read it from main memory".
You can use below links to understand more on volatile.
Read more: http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz4ZlvIJYzZ
Cave of Programming: https://www.youtube.com/watch?v=_aNO6x8HXZ0&t=113s
Related
In an application I'm working on I found the following code snippet:
public class MyClass {
private AtomicBoolean atomicBoolean = new AtomicBoolean(false);
public void Execute() {
// Whole lot of business logic
// ....
synchronized (this.atomicBoolean) {
// Want to make sure that execution is stopped if Stop() was called
if (this.atomicBoolean.get()) {
throw new SpecificException("...");
}
// Some more business logic...
}
}
public void Stop() {
synchronized (this.atomicBoolean) {
this.atomicBoolean.set(true);
}
}
}
According to FindBugs this is not correct as I can't use an AtomicBoolean together with synchronized and expect it to block the object.
My question is: What is the correct way to rewrite this methods? I've read about using an lock Object together with a boolean attribute instead but it appears kinda clumsy to introduce two new attributes for this lock.
Edit: As stated in a comment below: I think the intention is that in the two synchronized blocks, the AtomicBoolean can't be changed and that while one Thread is in one of the synchronized blocks, none other such block could be entered.
just replace the synchronized (this.atomicBoolean) { part from both methods, AtomicBoolean::get and AtomicBoolean::set is already atomic.
...I can't use an AtomicBoolean together with synchronized...
For whatever it's worth, the language allows you to synchronize on any object.
As a matter of style, some programmers prefer to only synchronize on a private object that is used for no other purpose.
private static Object foobarLock = new Object();
...
public void fooItUp(...) {
...
synchronized(foobarLock) {
...
}
...
}
...and expect it to block the object
Just to be clear, when some thread T enters a synchronized (o) {...} block, that does not prevent other threads from accessing or modifying the object o. The only thing it prevents is, it prevents some other thread U from entering a synchronized block on the same object o at the same time.
To my understanding the following code should terminate normally as the condition stopRunning = true; is met.
However, when I run this program it is printing only Last line of Main(), Start Method ended is never printed as the while loop is never terminated.
public class Test {
private static boolean stopRunning = false;
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
#Override
public void run() {
start();
}
}).start();
Thread.sleep(100);
stopRunning = true;
System.out.println("Last line of Main()");
}
public static void start() {
while (!stopRunning) {
}
System.out.println("Start Method ended.");
}
}
Please help me understand this behavior.
Changing the flag to volatile with
private static volatile boolean stopRunning = false;
will mean that other threads see the change immediately (from main memory instead of a cache), and the code executes as you expect. How volatile relates to Java's memory model is explained further e.g. in this tutorial.
As Mick stated, you should use the volatile keyword to synchronize your variable, so on a change the new value is written directly back to memory and your code will work as expected.
Be aware (also stated in the article Mick linked) that volatile does not guarantee to avoid race conditions, so if two different threads would read your variable, it is not safe that they both read the same value (despite everything is read from memory and on change directly written back)
As stated in previous answers:
Like Mike stated - in run() you should use Test.start() or rename the method. The start you are calling is the thread's start method.
Also as Mick stated, setting stopRunning as volatile should help. The reason it should work is that it will remove the caching of the variable in the thread's memory and will get/set directly from memory.
Ok so I just read this question Do you ever use the volatile keyword in Java?, and I get using a volatile variable in order to stop a loop. Also I've seen this reference, http://www.javamex.com/tutorials/synchronization_volatile.shtml. Now the article says that volatile variables are non-blocking. Also it says that it cannot be used for concurrency in a read-update-write sequence. Which makes sense because they're non-blocking.
Since volatile variables are never cached is it faster to simply use synchronization to stop the loop (from the earlier link)?
Edit: Using a synchronized solution
public class A{
private boolean test;
public A(){
test = true;
}
public synchronized void stop(){
test = false;
}
public synchronized boolean isTrue(){
return test;
}
}
public class B extends Thread {
private A a;
public B(A refA){
a = refA;
}
public void run(){
//Does stuff here
try{
sleep(1000);
}
catch(Exception e){}
a.stop();
}
public static void main(String [] args){
A TestA = new A();
B TestB = new B(TestA);
TestB.start();
while(TestA.isTrue()){
//stay in loop
System.out.println("still in loop");
}
System.out.println("Done with loop");
}
}
No, reading a volatile variable is faster than than reading an non-volatile variable in a synchronized block.
A synchronized block clears the cached values on entry which is the same as reading a volatile variable. But, it also flushes any cached writes to main memory when the synchronized block is exited, which isn't necessary when reading volatile variable.
There's a numebr of things wrong in your question: You can do a reliable read-update-write with volatile so long as you use Atomic*FieldUpdater and a cas-loop. Volatiles can be "cached", they just need to obey the relevant happens-before semantics specified.
Synchronisation typically involves obtaining a lock, which is relatively expensive (although may actually be quite cheap). Simple concurrent optimisations may use non-naive implementation techniques.
I was reading through Java Memory model and was playing with volatile. I wanted to check how Volatile will work in tandem with ThreadLocal. As per definition ThreadLocal has its own, independently initialized copy of the variable whereas when you use volatile keyword then JVM guarantees that all writes and subsequent reads are done directly from the memory. Based on the high level definitions i knew what i was trying to do will give unpredictable results. But just out of curiosity wanted to ask if someone can explain in more details as if what is going on in the background. Here is my code for your reference...
public class MyMainClass {
public static void main(String[] args) throws InterruptedException {
ThreadLocal<MyClass> local = new ThreadLocal<>();
local.set(new MyClass());
for(int i=0;i<5; i++){
Thread thread = new Thread(local.get());
thread.start();
}
}
}
public class MyClass implements Runnable {
private volatile boolean flag = false;
public void printNameTillFlagIsSet(){
if(!flag)
System.out.println("Flag is on for : " + Thread.currentThread().getName());
else
System.out.println("Flag is off for : " + Thread.currentThread().getName());
}
#Override
public void run() {
printNameTillFlagIsSet();
this.flag = true;
}
}
In your code you create a ThreadLocal reference as a local variable of your main method. You then store an instance of MyClass in it and then give that same reference of MyClass to 5 threads created in the main method.
The resulting output of the program is unpredictable since the threads are not synchronized against each other. At least one thread will see the flag as false the other four could see the flag as either true or false depending on how the thread execution is scheduled by the OS. It is possible that all 5 threads could see the flag as false, or 1 could see it false and 4 see it true or anything in between.
The use of a ThreadLocal has no impact on this run at all based on the way you are using it.
As most have pointed out you have deeply misunderstood ThreadLocal. This is how I would write it to be more accurate.
public class MyMainClass {
private static final ThreadLocal<MyClass> local = new ThreadLocal<>(){
public MyClass initialValue(){
return new MyClass();
}
}
public static void main(String[] args) throws InterruptedException {
local.set(new MyClass());
for(int i=0;i<5; i++){
Thread thread = new Thread(new Runnable(){
public void run(){
local.get().printNameTillFlagIsSet();
local.get().run();
local.get().printNameTillFlagIsSet();
}
});
thread.start();
}
}
}
So here five different instances of MyClass are created. Each thread will have their own accessible copy of each MyClass. That is Thread created at i = 0 will always have a different instance of MyClass then i = 1,2,3,4 despite how many local.get() are done.
The inner workings are a bit complicated but it can be done similar to
ConcurrentMap<Long,Thread> threadLocalMap =...;
public MyClass get(){
long id = Thread.currentThread().getId();
MyClass value = threadLocalMap.get(id);
if(value == null){
value = initialValue();
threadLocalMap.put(id,value);
}
return value;
}
To further answer your question about the volatile field. It is in essence useless here. Since the field itself is 'thread-local' there will be no ordering/memory issues that can occur.
Just don't divinize the JVM. ThreadLocal is a regular class. Inside it uses a map from current thread ID into an object instance. So that the same ThreadLocal variable could have its own value for each thread. That's all. Your variable exists only in the main thread, so it doesn't make any sence.
The volatile is something about java code optimization, It just stops all possible optimizations which allow avoid redundant memory reads/writes and execution sequence re-orderings. It is important for expecting some particular behaviour in multi-threaded environment.
You have two big problems:
1) As many pointed out, you are not using ThreadLocal properly so you don't actually have any "thread local" variables.
2) Your code is equivalent to:
MyClass someInstance = new Class();
for (...)
... new Thread(someInstance);
so you should expect to see 1 on and 4 off. However your code is badly synchronized, so you get random results. The problem is that although you declare flag as volatile, this is not enough for good synchronization since you do the check on flag in printNameTillFlagSet and then change the flag value just after that method call in run. There is a gap here where many threads can see the flag as true. You should check the flag value and change it within a synchronized block.
You main thread where you have a ThreadLocal object is being passed to all the threads. So the same instance is being passed.
So its as good as
new Thread(new MyClass());
What you could try is have an object being called by different threads with a thread local variable. This will be a proper test for ThreadLocal where each thread will get its own instance of the variable.
Ok so I just read this question Do you ever use the volatile keyword in Java?, and I get using a volatile variable in order to stop a loop. Also I've seen this reference, http://www.javamex.com/tutorials/synchronization_volatile.shtml. Now the article says that volatile variables are non-blocking. Also it says that it cannot be used for concurrency in a read-update-write sequence. Which makes sense because they're non-blocking.
Since volatile variables are never cached is it faster to simply use synchronization to stop the loop (from the earlier link)?
Edit: Using a synchronized solution
public class A{
private boolean test;
public A(){
test = true;
}
public synchronized void stop(){
test = false;
}
public synchronized boolean isTrue(){
return test;
}
}
public class B extends Thread {
private A a;
public B(A refA){
a = refA;
}
public void run(){
//Does stuff here
try{
sleep(1000);
}
catch(Exception e){}
a.stop();
}
public static void main(String [] args){
A TestA = new A();
B TestB = new B(TestA);
TestB.start();
while(TestA.isTrue()){
//stay in loop
System.out.println("still in loop");
}
System.out.println("Done with loop");
}
}
No, reading a volatile variable is faster than than reading an non-volatile variable in a synchronized block.
A synchronized block clears the cached values on entry which is the same as reading a volatile variable. But, it also flushes any cached writes to main memory when the synchronized block is exited, which isn't necessary when reading volatile variable.
There's a numebr of things wrong in your question: You can do a reliable read-update-write with volatile so long as you use Atomic*FieldUpdater and a cas-loop. Volatiles can be "cached", they just need to obey the relevant happens-before semantics specified.
Synchronisation typically involves obtaining a lock, which is relatively expensive (although may actually be quite cheap). Simple concurrent optimisations may use non-naive implementation techniques.