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.
Related
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
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.
I wrote an example trying to understand volatile.
public class VolatileExample {
private volatile boolean close = false;
public void shutdown() {
close = true;
}
public void work(){
Thread t1 = new Thread(new Runnable(){
public void run(){
while (!close) {
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
while (!close) {
shutdown();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args){
VolatileExample volatileExample = new VolatileExample();
volatileExample.work();
}
}
it did stop as I expected. However, when I took the volatile away from the close tag, I have tried a lot of times---I expect the program will not stop because the thread t1 cannot see the change made by thread t2 on the close variable, but the programs ended successfully everytime. So I am confused, now that we can do it without volatile, what is volatile used for? Or can you give a better example that can make a difference between using volatile and not using volatile?
Thank you!
The memory model says only that changes to non- volatile fields may not be visible in other threads.
Perhaps your runtime environment was in a cooperative mood.
Changes to nonvolatile fields are sometimes visible to other threads, and sometimes not. How long they take to be visible to other threads can vary by orders of magnitude depending on what other processing the machine is doing, the number of processor chips and cores on the machine, the architecture of the cache memory on the machine, etc.
Ultimately, though, it comes down to this: buggy concurrency code can succeed the first 999,999 times, and fail on the millionth time. That often means it passes all tests, then fails in production when things really matter. For that reason, it's important when writing concurrent code that one make the best possible effort to ensure the code is correct - and that means using volatile for variables accessed from multiple threads even when it doesn't seem to make a difference in testing.
I was going through some simple examples on threading/synchronizing from a book that claims the use of synchronized will allow access to the method by one thread being called on the same instance. It does serialize as promised but it seems that about 9/10 times the third Caller created in the Synch main method below comes before the second. This code is the example code showing the issues without a synchronized method.
class CallMe {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("CallMe Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
CallMe target;
Thread t;
public Caller (CallMe target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread(this);
t.start();
}
#Override
public void run() {
target.call(msg);
}
}
class Synch {
public static void main(String args[]) {
CallMe target = new CallMe();
Caller c1 = new Caller(target, "Hello");
Caller c2 = new Caller(target, "Synchronized");
Caller c3 = new Caller(target, "World");
try {
c1.t.join();
c2.t.join();
c3.t.join();
} catch (InterruptedException e) {
System.out.println("Synch Interrupted");
}
}
}
The book shows two ways to deal with the issue, they are -
synchronized void call(String msg) {...} and
public void run() { synchronized (target) {...} }
It's clear that both options work because, as opposed to the original code, the bracketed words are consistent like...
[Hello]
[World] (about 90% of the time the calls are backwards)
[Synchronized](1/many have Synchronized as the first msg)
...there's no rhyme or reason to the original code. So I know it's "working" and can be seen directly by placing breakpoints on each of the Caller instantiations. It works every time, obviously to me, when I do.
Why is the third Caller consistently calling call before the second?
Threads by definition run in parallel, and none is given precedence over any other.
Once the threads are all launched it is essentially random which will run first, in general the first one launched will have a slight "head start" but that head start is tiny compared to the overhead of launching threads etc.
A quirk of your particular environment just happens to be favoring one thread, the results may well vary on different systems and certainly shouldn't be relied on.
Incidentally this is bad practice for a number of reasons:
public Caller (CallMe target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread(this);
t.start();
}
(You probably got a compiler warning in fact).
Much better is to provide a start method
public Caller start() {
t.start();
return this;
}
and then do
new Caller(target, msg).start();
This absolutely ensures that the Caller object is fully initialized and ready to go before the Thread starts processing it.
Why is the third call consistently calling call before the second?
It's not doing so consistently - it's doing so about 90% of the time.
Basically, synchronization isn't guaranteed to be first-in, first-out... and there's no guarantee that the calls will even be made in the order you're expecting. Three new threads are being started in quick succession - there is no guarantee about which thread will actually start executing its code first.
Fundamentally if you want to impose ordering on parallel code, you need to do so explicitly. Synchronization doesn't provide ordering - it only provides exclusivity.
It does serialize as promised but it seems that about 9/10 times the third Caller created in the Synch main method below comes before the second.
Be careful to understand the meaning of "serialize" in your sentence: it means that all the code sections protected by the same lock will never run in parallel; in other words, their execution will be serial.
What it doesn't mean is "execution of these code sections will occur in a strict, specified order". It will not.