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
Related
You might think that this question is duplicate of this one but no answers of that question helps me for understanding synchronized method in android. I searched a lot on google for understanding synchronized methods and i found some answer but they didn't help me to perfectly understand Synchronized methods because no answer has any perfect practical example.
I have tried to understand synchronized method by implement 2 synchronized methods in my code and executing them concurrently but i am failed in properly implementing them. So, please provide explanation of synchronized method with simple example so, others like me also can understand it simply and in a faster way.
UPDATE
I am not sure i am going in right direction or not but i have tried following code which have 2 synchronized methods.
synchronized void add() {
counter++;
Log.e("JK", String.valueOf(counter));
}
synchronized void minus() {
counter--;
Log.e("JK", String.valueOf(counter));
}
and i have called this methods in two different threads using below code.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
synchronized (counter++) {
add();
}
}
},500);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
minus();
}
},1000);
Synchronized method is a method which can be used by only one thread at a time.
Other threads will be waiting until the method will be released.
You should have only serious reasons to declare method as synchronized because such method decreases the productivity. The classic case of synchronized method usage is when several threads are using same resources i.e. change state of some object and it is needed to make sure only one thread performs it at a time, otherwise it will cause inconsistency. Also make sure to make synchronized method as small as possible, ideally reduce it to contain only operations which can manipulate common resources.
For example the class Reporter has common resource fileWriter. It writes to file some messages with information about authors.
class Reporter{
private FileWriter fileWriter;
public synchronized void addRecord(String author, String message) throws IOException {
fileWriter.write("\n<<<<<<<<<<>>>>>>>>>>\n");
fileWriter.write("Message written by:" + author + "\n");
fileWriter.write("Message content:" + message);
}
public Reporter(FileWriter fileWriter) {
this.fileWriter = fileWriter;
}
}
Suppose you are running this code from 2 different threads:
Reporter reporter = new Reporter("path/report");
...
Thread thread = new Thread(){
public void run(){
reporter.addRecord("John", "Hi");
}
}
thread.start();
Thread thread2 = new Thread(){
public void run(){
reporter.addRecord("Bill", "Hello");
}
}
thread2.start();
The result for synchronized method will be like this :
<<<<<<<<<<>>>>>>>>>>
Message written by:John
Message content:Hi
<<<<<<<<<<>>>>>>>>>>
Message written by:Bill
Message content:Hello
If method is not synchronized several threads may write to file simultanously, which can cause an unpredictable sequence in file, like this:
<<<<<<<<<<>>>>>>>>>>
<<<<<<<<<<>>>>>>>>>>
Message written by:John
Message written by:Bill
Message content:Hello
Message content:Hi
Synchronized method is a method which can be used by only one thread at a time. Other threads will be waiting until the method will be released. You should have only valid reasons to declare method as synchronized because such method decreases the productivity and performance.
I am not very good at multithreading and am baffled by this code:
public class Main {
public static void main(String... args) throws Exception {
new Thread(Main::test).start();
}
private static synchronized void test() {
new Thread(Main::test).start();
System.out.println("TEST");
}
}
Can it result in a deadlock or not? If so, then why have I not been able to get it to deadlock? My thinking is, thread 1 acquires lock on test(), then another thread, created in test() tries to acquire it and they should be waiting on each other. But they aren't, why not?
I know, that adding join() in test() will make it result in a deadlock, but how come the example below doesn't use joins and deadlocks?
This code results in a deadlock literally every time I run it:
public class Main {
public static void main(String... args) {
new Thread(Main::test).start();
new Thread(Main::test2).start();
}
private static void test() {
synchronized (Integer.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
synchronized (Float.class) {
System.out.println("Acquired float");
}
}
}
private static void test2() {
synchronized (Float.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
synchronized (Integer.class) {
System.out.println("Acquired integer");
}
}
}
}
No, the code in the first example cannot deadlock. The newly started threads will simply wait until the previous thread exits the method to acquire the lock.
The code in the second example deadlocks because the locks are acquired in opposite order and because of the sleeps are reliably going to block each other.
When you're at the phase where you're first learning how to think about concurrency and related problems, I would very much recommend using physical props to keep your thoughts and hypotheses clear and explicit.
For example, grab a A3 sheet of paper, set up a "race track" where you use something like Monopoly pieces to signify what you're doing in your code, what you expect to happen, and what your experiments show actually happens.
When your experiments don't work out, take a small piece of the beginning first, and verify it. Then add some more, and so on.
It helps if you read about how actual computers (not the CS ideal or conceptual computers) currently work. How the CPU gets data out of the main memory into its cache. How two or three CPUs decide which one of them can handle data in one cache line at a time. Then, how the Java Memory Model needs you to write your source code so that the JVM knows what you actually mean to happen.
I'm working on some sensitive LWJGL code and need to make sure that I create my display, and therefore GL context before executing any other code.
To give a clear example of my current predicament, take the following:
public static void main(String[] args) {
GLDisplay display = new GLDisplay();
display.start();
GLShader shader = new StaticShader();
}
The beginning of my GL creation happens in display.start(), where a separate thread is created, and within the separate thread, my Display is created.
Except this is where the problem lies, I have it in a separate thread. So then my program goes on and starts prematurely executing the new StaticShader() which calls even more GL code, breaking the program. (Can't execute before display is created).
What I'm trying to do, is achieve two threads simultaneously which I already have, but make sure that start() method is called completely before anything else is.
Here is how the start method works:
public synchronized void start() {
Threader.createThread(this, "GLDisplay");
}
#Override // public class GLDisplay extends Runnable
public void run() {
// GL code goes here.
}
And here is Threader:
public static void createThread(Runnable behaviour, String name) {
new Thread(behaviour, name + behaviour.hashCode()).start();
}
Now you may notice the synchronized keyword in the start method, well thats just one attempt I've had to no avail. I've also tried the following (which I actually grabbed from another StackOverflow answer):
#Override
public void run() {
synchronized(this) {
// GL code
}
}
I've checked other StackOverflow answers but either don't understand them or don't help me in my case. With the first code block I give in the main method, that is how I want my code to look to the person using it. I'm trying to put the thread-creation inside GlDisplay to hide it.
Any ideas?
Edit:
I can't simply wait for GLDisplay to close either (with Thread.join()) because there lies a while-loop that updates the display for the entirety of the program.
This is the entire reason I multi-threaded it. To allow this forever-ending loop to run while I do other things in the program. By closing the thread, I close the loop, cleanup the display and free the GL context from memory, once again making the shader code fail for lack of an existing context.
You can use java.util.concurrent.CountDownLatch to achieve it which aids in making a thread(s) wait till the operations on other threads is complete. Please see the reference on on what and how to use it.
Example:
public static void main(String[] args) {
CountDownLatch cdl = new CountDownLatch(1);
// pass the CountDownLatch into display
GLDisplay display = new GLDisplay(cdl);
display.start();
// wait for the latch to have been counted down in the disp thread
try
{
cdl.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
GLShader shader = new StaticShader();
}
In your GLDisplay thread, call the countDown method of CountDownLatch
I might be misunderstanding something, but try the following:
public static void createThread(Runnable behaviour, String name) {
Thread t = new Thread(behaviour, name + behaviour.hashCode()).start();
t.join();
}
By calling join() the program should wait for the thread to complete.
Well I remember now that I can't have GL code against two separate threads anyway, but thats besides the point.
I don't actually need to use any thread-lock classes or anything, but rather can just do something as simple as this:
private Boolean threadLock = true;
public void start() {
Threader.createThread(this, "GLDisplay");
while (true) {
synchronized(threadLock) {
if (!threadLock) break;
}
}
}
#Runnable
public void run() {
// Do GL code.
synchronized(threadLock) { threadLock = false; }
// Do the rest of whatever I'm doing.
}
When the threadlock is reached in the second thread and is released, the first thread continues doing it's activity. It's that simple!
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.
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.