Why do primitive variable in multithreading little program, behave as a volatile variable? Please help me in my code.
/**
* Practice with threads problem visibility.
* #author Matevosyan Vardan
* #version 1.0
* created on 21.09.2017
*/
public class VisibilityProblem {
private static int countingVal = 0;
public static int getCountingVal() {
return countingVal;
}
Start in main
public static void main(String[] args) throws InterruptedException {
Thread looperR = new VisibilityProblem.Looper();
Thread listener = new VisibilityProblem.Listener();
listener.start();
looperR.start();
listener.join();
looperR.join();
}
Class to wright and increase counting variable after sleep 500 millisecond
to wait a little, what helps do some staff Listener thread.
public static class Looper extends Thread {
#Override
public void run() {
while (VisibilityProblem.countingVal < 5) {
VisibilityProblem.countingVal++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("increase " + VisibilityProblem.countingVal);
}
}
}
Class to read and assign counting value
public static class Listener extends Thread {
#Override
public void run() {
int localCount = VisibilityProblem.countingVal;
while (localCount < 5) {
if (localCount != VisibilityProblem.countingVal) {
System.out.println("It is " + localCount + " now");
localCount = VisibilityProblem.countingVal;
}
}
}
}
}
Why do primitive variable in multithreading little program, behave as a volatile variable
It depends what you mean by behave as a volatile variable.
If you mean, why are changes made by one thread seen in the second thread ... then the reason is that the JLS allows this.
If you mean, why are changes made by by one thread guaranteed to be seen in the second thread ... then your program does not provide evidence1 of this!!
The difference in visibility semantics between ordinary and volatile variables are:
For a volatile, the changes are guaranteed to be immediately visible.
For an ordinary variable, the changes may be visible immediately, or with a delay, or ... never. Any of those behaviors conforms with the Java Memory Model.
Seeing the changes with ordinary variables when you run the program on one hardware platform with one version of the Java compiler on a computer running with one set of applications running, etc, etc does not mean that you will always see that in all circumstances.
1 - Indeed, it is theoretically impossible to write a program that can do this. But your program could provide evidence that this is not guaranteed ... or that a (hypothetical) guarantee is not being met.
Related
This code end up with different results if I change the parameter of sleep(), and here is some sample outcomes:
1.sleep(1l), the thread will always terminate automaticlly, the "Stoped" statement will always be printed, and the icon of "Terminate" in Eclipse will be grey too. (seems working perfectly huh?)
2.sleep(1000l), here comes the problem, if main thread sleeps for 1 second, the Thread v will never terminated automaticlly, the "Stoped" will not be printed, and the icon of "Terminate" is red, which means there is still some thread running.
I know it could be solved if I add "volitale" for the parameter "isRunning", but I wonder why and how does the sleep() statement affect the outcome?
PS:I'm a newbie for both java and english, so I apologize for any possible discomforts due to this question.
public class VolitaleTest {
public static void main(String[] args) throws InterruptedException {
Vo v = new Vo();
new Thread(v).start();
Thread.sleep(1000l);
v.setRunning(false);
System.out.println(v.i);
}
}
class Vo implements Runnable {
private boolean isRunning = true;
int i = 0;
public void run() {
while (isRunning) {
i++;
// System.out.println("Running");
/*
* Once you add this statement, you will always be able to terminate
* the program automatically, no matter how long the thread sleeps.
*/
}
System.out.println("Stoped.");
}
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
}
volatile makes it possible for what one thread wrote up to and including writing to the volatile variable to be visible to another thread starting from when it reads that variable. If the variable is not volatile then that happens-before memory relationship is not guaranteed.
I'm doing a short course about Threads in Java, in one of my homeworks they asked me: ¿Why you don't should be synchronize the run method? show an example.
I searched about it, and that i think is use synchronized for a run method is not useful, at least commonly. Because the people don't call the run method manually, so the synchronized effect isn't visible creating multiple instances of a object with synchronized run.
So, i would like know if exist another reason or if i'm wrong.
Syncrhonizing the run() method of a Runnable is completely pointless unless you want to share the Runnable among multiple threads and you want to serialize the execution of those threads. Which is basically a contradiction in terms.
If the run method of a Runnable were synchronized, then either
a) you have many runnables (in which case, no need to synchronise, as each one is called on a different object), or else
b) you have one runnable being called in many threads - but then they clearly won't run in parallel -- thus defeating the purpose of having multiple threads!
You may synchronize on run method, nothing wrong with it. I think the reasons behind this advice should be explained to you by the instructor of course.
We need synchronization when there are shared resources (between threads).
Synchronizing on a method is same as synchronizing on this which will block other method calls.
As a counter example, a poor man's Future implementation;
public class SynchronizedRun {
static abstract class Future<T> implements Runnable{
private T value;
public synchronized T getValue(){
return value;
}
protected void setValue(T val){
value = val;
}
}
public static void main(String[] args) {
Future<Integer> longRunningJob = new Future<Integer> (){
#Override
synchronized public void run() {
try {
Thread.sleep(5000);
setValue(42);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(longRunningJob).start();
System.out.println("getting results");
System.out.println("result = " + longRunningJob.getValue());
}
}
This code is from Effective Java (Item 66): (without sync or volatile this never ends)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
As Bloch mentioned in that chapter it will never write "finished" to the console. I've been playing around with this class, and add that line to the runnable run method:
System.out.println("im still running");
With this the while loop doesn't only increment i but prints out this string in every loop. But what drives me crazy, that this way the thread stops after 1 sec, when main thread comes back from sleep.
modified: (stops without volatile/sync)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;System.out.println("im still running");}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
So what is the logic behind this?
Precisely, it is just not guaranteed that the thread will ever stop, but it is not forbidden that it does stop. The logic behind this is provided by the Java Memory Model, which is a rather complicated topic, but needed in order to understand Multithreading in Java.
The concept is that a write to a non-volatile field of one thread is only required to be seen by another thread if these two actions synchronize with each other. A compiler is allow to reorder some actions if the behavior exhibited by the thread it is executed in does not change. But another thread might see this. So you need proper synchronization in order to tell the compiler that reordering is not allowed in some parts.
Read the full paper about this here: JSR-133
Writing data to the console is often implemented a thread safe operation.
In that case your act of writing data to the console can also trigger updating of the canrunstatic variable as seen by your backgroundThread.
Note that this is not promised by the Java Memory Model, nor by the implementation of java System.out
I'm just testing some concurrent programming in Java.
Basically I have a class (Light) which is a kind of finite state machine, and changing its state regarding the commands.
That's what I'm trying to: The light is in ON state, I send a command to the thread of this class for changing the state in OFF.
But I got a problem during the execution.
First, let me present the class:
enum State {ON, OFF};
public class Light implements Runnable {
private boolean cmdOn;
private boolean cmdOff;
State state;
public Light() {
cmdOn = false;
cmdOff = false;
state = State.ON;
}
#Override
public void run() {
while(true) {
switch(state) {
case ON:
if(cmdOff) {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = State.OFF;
}
break;
case OFF:
if(cmdOn) {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = State.ON;
}
break;
}
}
}
public void setCmdOn(boolean cmdOn) {
this.cmdOn = cmdOn;
}
public void setCmdOff(boolean cmdOff) {
this.cmdOff = cmdOff;
}
public State getState() {
return state;
}
}
And my main class:
public class Main {
public static void main(String args[]) throws InterruptedException {
Light light = new Light();
Thread t = new Thread(light);
t.start();
printState(light, 500, 1);
light.setCmdOff(true);
printState(light, 500, 4);
}
public static void printState(Light l, int time, int number) throws InterruptedException {
for(int i= 0; i < number; i++) {
System.out.println(l.getState());
Thread.currentThread().sleep(time);
}
}
The output shows me that I'm stuck in the ON state while I should be in OFF state.
In a second run, after putting an instruction (System.out.println or whatever...) above the if statement which verify that cmdOff is true, it's magically works.
I don't understand why the cmdOff variable is not pass to true during the first run !?
And why in the second run it works?
I miss something, probably a synchronizing block. But I don't find the explanation to deal with this.
Thanks.
Best regards,
You should read about synchronization. Without synchronization you risk getting visibility errors where one thread can't see changes another thread made to a variable shared between the threads.
Tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
You can use a synchronized block that uses an object both threads know about to do locking. If both threads always synchronize on that known object when reading or updating your shared data, then visibility and atomicity will never be an issue.
Read here to fully understand "synchronized": http://tutorials.jenkov.com/java-concurrency/synchronized.html
You should also be able to just declare the shared variable as volatile. This means all writes and reads on it create a happens-before relationship with other threads, which is what you want. Read the tutorial above to fully understand the issues and terminology.
Read here to fully understand "volatile": http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html.
Try using volatile on cmdOn and cmdOff:
private volatile boolean cmdOn;
private volatile boolean cmdOff;
Volatile variable explanation in Java docs
Without it (or synchronization) changes may not be visible.
Without any synchronization, there are no guarantees that the running thread will ever see the values written to cmdOff and cmdOn by the other thread. Also, lack of synchronization on state means any changes by the running thread may not be seen by the other thread. Try making cmdOn, cmdOff and state volatile .
I have a class.
I initialize a variable in the constructor of that class.
I call a method that contains a while loop and increments the variable each time through.
I wrote a test to check the value of the variable after the method has been called (and goes through the while loop one time).
public class ThreadGenerator implements Runnable {
private int requests;
private int limit;
public ThreadGenerator() {
requests = 0;
}
public void setRequestLimit(int anyLimit) {
this.limit = anyLimit;
}
public void generateThread() {
new Thread(this).start();
}
public void run() {
while(requests < limit) {
try {
// do some stuff
requests++;
// close some stuff
} catch (IOException e) {
e.printStackTrace();
}
}
}
public int getRequests() {
return requests; // calling this method from my tests always returns 0
}
In my test, when I create a new instance of this class, then call this method on that class, it runs correctly and it increments the request counter correctly. I've tried several print statements to make sure of that. But if I call getRequests on my ThreadGenerator object in my test, it will return 0, the amount it was initialized with.
My test code:
ThreadGenerator threadGenerator = new ThreadGenerator();
threadGenerator.setRequestLimit(1);
threadGenerator.generateThread();
assertEquals(threadGenerator.getRequests(), 1);
How can I modify this variable I initialized in the constructor and gain access to it in my test suite?
Bear in mind that just because you ask Java to create a new thread with a Runnable, doesn't mean that the run() method will be called immediately. It's likely the case that the assertEquals is happening before the run happens the first time.
You may want to return the thread and call join in the test on the generated thread, which will ensure that the Thread runs until it dies, possibly with a short timeout.
/* in the system under test */
#VisibleForTesting Thread generateAndReturnThread() {
Thread thread = new Thread(this);
thread.start();
return thread;
}
public void generateThread() {
generateAndReturnThread();
}
/* in the test */
#Test public void yourTest() {
ThreadGenerator threadGenerator = new ThreadGenerator();
threadGenerator.setRequestLimit(1);
// wait up to a second for thread to complete
threadGenerator.generateThreadAndReturn().join(1000);
assertEquals(threadGenerator.getRequests(), 1);
}
Side note: Consider AtomicInteger for your requests class, if multiple threads might modify requests. This will help prevent two different threads from both modifying requests and overwriting one another.
In addition to above answer, consider declaring the variable as volatile, so that you can actually get the latest value after another thread incremented the variable.