Different outcome of java multi-thread due to length of sleep()? - java

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.

Related

Volatile variable in multithreading program in java

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.

Why do thread behave different with different run method body?

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

Thread switch/case ignoring statement

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 .

Problems with multithread programming in Java [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm studying Java using the book by Gosling. There is a question in the chapter devoted to the multithread programming:
Write a program, which will create a message each second from the beginning of the session. Another thread of this program should create a message each 15 sec. You should provide the possibility of every second-notification by the thread which is counting time.
Here is my solution (it doesn't work and i can't understand why, i think, i just can't properly understand the principle on creating a thread):
public class test {
public static void main (String [] args) throws InterruptedException{
chrono my=new chrono();
my.timer();
Runnable t1=new messenger(5);
Runnable t2=new messenger(1);
new Thread(t1, "t1").start();
new Thread(t2, "t2").start();
}
}
class chrono {
static int time=0;
public synchronized void timer() throws InterruptedException {
Thread.sleep(1000);
time++;
System.out.println(time);
notifyAll();
}
}
class messenger implements Runnable {
int time;
messenger(int time) {
this.time=time;
}
synchronized void timerListener() {
try {
while (chrono.time%time!=0) {
wait();
}
System.out.println("Thread "+this.time);
} catch(InterruptedException e) {}
}
public void run() {
timerListener();
}
}
New version:
public class test {
public static void main (String [] args) throws InterruptedException{
Chronometr my=new Chronometr();
Runnable t1=new Messenger(5, my);
new Thread(t1, "t1").start();
for (int i=0;i<6;i++) {
synchronized(my) {
my.timeCount();
my.notifyAll();
}
}
}
}
class Chronometr {
static int time=0;
public void timeCount() throws InterruptedException {
Thread.sleep(1000);
time++;
System.out.println(time);
}
}
class Messenger implements Runnable{
int time;
public Chronometr ch;
Messenger(int time, Chronometr ch) {
this.time=time;
this.ch=ch;
}
public void waitForTime() {
synchronized (ch) {
try{
while (Chronometr.time%time!=0)
ch.wait();
System.out.println("Thread "+this.time);
}
catch(InterruptedException e) {}
}
}
public void run() {
waitForTime();
}
}
Last change:
public class test {
public static void main (String [] args) throws InterruptedException{
Chronometr my=new Chronometr();
Runnable t1=new Messenger(5, my);
new Thread(t1, "t1").start();
for (int i=0;i<10;i++) {
synchronized(my) {
Chronometr.time+=1;
System.out.println(Chronometr.time);
my.notifyAll();
//my.wait();
}
Thread.sleep(1000);
}
}
}
Edit: Just noticed another big problem: The code calls Thread.sleep() inside a synchronized block. No! No! No! No! No!
When I run the newer version of your program as-is, the Messenger thread usually never gets to run: Here's what I think happens:
main thread messenger thread
----------- ----------------
starts messenger
locks chronometer
sleeps enters waitForTime()
blocks trying to lock
chronometer
---one second later---
wakes up from sleep
increments time
prints message
calls notifyAll()
(Has no effect, 'cause
messenger is not in
wait() call)
ulocks the lock
re-locks the lock wakes up
sleeps blocks trying to lock
chronometer
. .
. .
. .
Try moving the Thread.sleep(1000) call out of the Chronometer.timeCount() method, into the main() method, outside of the synchronized(my) block. I'm guessing that the output will be more like what you expected.
Original answer below the line,
Your biggest problem is this:
chrono.timer() method calls notifyAll() on itself (i.e., on the chrono instance referenced by the "my" variable in main()). Who calls wait() on that object? Nobody is who. Your messanger objects wait() on themselves. Who notifies them? Nobody is who.
Other comments (in no particular order):
(1) Class names should be CamelCase beginning with a capital letter. The more your code looks like everybody else's, the more everybody else will be willing to try to understand it and help you out.
(2) If you have only one variable of type FooBarBaz, then the variable should be named fooBarBaz. Same reason.
(3) Class names should be nouns (e.g., Chronometer instead of the ambiguous chrono), method names should be verbs (e.g., waitForTimerTick() instead of timerListener()). Same reason.
(4) the my.timer(); call in main could not have any possible effect on the threads that you create and start after it returns. A foo.notify() call does nothing if there are no other threads already waiting in foo.wait() when notify() is called.
(4a) A variable named "my" is an abomination.
(5) the my.timer() call waits for one second, increments my.time, notifies nobody, and then it's done. For good. In particular, nobody will ever increment my.time again.
(5a) The problem statement clearly says that the program should go on forever periodically printing out messages, but there are no loops in your program except for the wait() loop in messenger.timerListener().
(6) You might want to get some more experience writing single-threaded programs that solve real problems before you try to tackle threads.

Thread stops itself

I've been searching for a solution for a long time, but I wasn't able to find one, so I'll ask my question here.
I have a thread which is started when the program starts and supposed to be idle until it is enabled by the application. Simple code example:
private class UpdaterThread extends Thread {
private static final int UPDATE_RATE = 50;
private Timer updateTimer = new Timer();
private boolean enabled;
public void run() {
while (!closeRequested) {
// If this is uncommented, the thread works as it's supposed to.
// System.out.print("");
if (enabled) {
Snapshot next = getNextSnapshot(1f / UPDATE_RATE);
System.out.println("Got next Snapshot");
updateTimer.sync(UPDATE_RATE);
System.out.println("Push");
currentSnapshot = next;
}
}
}
public void enable() {
enabled = true;
}
public void disable() {
enabled = false;
}
}
When you read a variable, which the JIT believes you didn't modify, it inlines the value. If you then modify the value later, it is too late, the value has been embedded in the code.
A simple way to avoid this is to use volatile but you would still have the problem than the thread is busy waiting for the value to change and there doesn't appear to be a good reason to do this. Another option is to add code which confuses the JIT do it doesn't do this optimisation. An empty synchronized block is enough but a friendlier way is to use Thread.sleep() which at least doesn't use up all your CPU.
I suggest using a volatile fields and sleeping with a period of 10-100 ms. However a simpler option is to not start the thread until it is needed.
since run() is called when the thread is started, you could just wait until later in the program to start it, also threads do not extend "Thread" but implements "Runnable" so the class definition would look like:
public class UpdaterThread implements Runnable
hope it helps :D

Categories