class Downloader extends Thread {
private InputStream in;
private OutputStream out;
private ArrayList<ProgressListener> listeners;
public Downloader(URL url, String outputFilename) throws IOException {
in = url.openConnection().getInputStream();
out = new FileOutputStream(outputFilename);
listeners = new ArrayList<ProgressListener>();
}
public synchronized void addListener(ProgressListener listener) {
listeners.add(listener);
}
public synchronized void removeListener(ProgressListener listener) {
listeners.remove(listener);
}
private synchronized void updateProgress(int n) {
for (ProgressListener listener: listeners)
listener.onProgress(n);
}
public void run() {
int n = 0, total = 0;
byte[] buffer = new byte[1024];
try {
while((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
total += n;
updateProgress(total);
}
out.flush();
} catch (IOException e) { }
}
}
The above code is from the book "seven concurrency models in seven weeks". The book says the above code is having potential for the deadlock as the the synchronized method updateProgress calls a alien method[onProgress] that might acquire another lock.
Since we acquire two locks without right order, the deadlock might occur.
Can anyone explain how the deadlock happens in the above scenario?
Thanks in advance.
It's best to make the objects you use with synchronized private.
Since you synchronize on the Downloader, you don't know whether other threads synchronize on the Downloader too.
The following listener causes a deadlock:
MyProgressListener extends ProgressListener {
public Downloader downloader;
public void onProgress(int n) {
Thread t = new Thread() {
#Override
public void run() {
synchronized(downloader) {
// do something ...
}
}
};
t.start();
t.join();
}
}
Code that deadlocks:
Downloader d = new Downloader(...);
MyProgressListener l = new MyProgressListener();
l.downloader = d;
d.addListener(l);
d.run();
The following will happen if you run that code:
the main thread reaches the updateProgress and aquires a lock on the Downloader
the MyProgressListener's onProgress method is called and the new thread t is started
the main thread reaches t.join();
In this situation the main thread cannot procede until t is finished, but for t to finish, the main thread would have to release it's lock on the Downloader, but that won't happen since the main thread can't procede -> Deadlock
First off, recall that the keyword synchronized, when applied to a a class, implies locking the whole object this method belongs to. Now, let's sketch out another couple of objects triggering the deadlock:
class DLlistener implements ProgressListener {
private Downloader d;
public DLlistener(Downloader d){
this.d = d;
// here we innocently register ourself to the downloader: this method is synchronized
d.addListener(this);
}
public void onProgress(int n){
// this method is invoked from a synchronized call in Downloader
// all we have to do to create a dead lock is to call another synchronized method of that same object from a different thread *while holding the lock*
DLthread thread = new DLThread(d);
thread.start();
thread.join();
}
}
// this is the other thread which will produce the deadlock
class DLThread extends Thread {
Downloader locked;
DLThread(Downloader d){
locked = d;
}
public void run(){
// here we create a new listener, which will register itself and generate the dead lock
DLlistener listener(locked);
// ...
}
}
One way to avoid the dead lock is to postpone the work done in addListener by having internal queues of listeners waiting to be added/removed, and have Downloader taking care of those by itself periodically. This ultimately depends on Downloader.run inner working of course.
Probably the problem in this code:
for (ProgressListener listener: listeners)
listener.onProgress(n);
When one thread, which holds a lock, calls an external method
like this one (onProgress) then you cannot guarantee that
implementation of this method won't try to obtain other lock,
which could be held by different thread. This may cause a deadlock.
Here's a classic example that shows the kind of hard-to-debug problems the author is trying to avoid.
The class UseDownloader is created and downloadSomething is called.
As the download progresses, the onProgress method is called. Since this is called from within the synchronized block, the Downloader motinor is locked. Inside our onProgress method, we need to lock our own resource, in this case lock. So when we are trying to synchronize on lock we are holding the Downloader monitor.
If another thread has decided that the download should be canceled, it will call setCanceled. This first tests done so it synchronized on the lock monitor and then calls removeListener. But removeListener requires the Downloader lock.
This kind of deadlock can be hard to find because it doesn't happen very often.
public static final int END_DOWNLOAD = 100;
class UseDownloader implements ProgressListener {
Downloader d;
Object lock = new Object();
boolean done = false;
public UseDownloader(Downloader d) {
this.d = d;
}
public void onProgress(int n) {
synchronized(lock) {
if (!done) {
// show some progress
}
}
}
public void downloadSomething() {
d.addListener(this);
d.start();
}
public boolean setCanceled() {
synchronized(lock) {
if (!done) {
done = true;
d.removeListener(this);
}
}
}
}
The following example leads to a deadlock because the MyProgressListener tries to acquire the Downloader lock while it's already acquired.
class MyProgressListener extends ProgressListener {
private Downloader myDownloader;
public MyProgressListener(Downloader downloader) {
myDownloader = downloader;
}
public void onProgress(int n) {
// starts and waits for a thread that accesses myDownloader
}
}
Downloader downloader = new Downloader(...);
downloader.addListener(new MyListener(downloader));
downloader.run();
Related
I was doing some thought experiment and here is my MyRunnable class:
class MyRunnable implements Runnable {
private final Integer mNumber;
private final CompleteHandler<Integer> mCallback;
public MyRunnable(Integer i, CompleteHandler<Integer> ch) {
mNumber = i;
mCallback = ch;
}
public void run() {
int sum = 0;
for (int i = 1; i <= mNumber; i++) {
sum += i;
}
mCallback.onFinished(sum);
}
}
This will be executed by a background thread which I create on the main thread, under the execute() method
public class Demo implements CompleteHandler<Integer>{
public static void main(String[] args) {
Demo d = new Demo();
d.execute();
}
#Override
public void onFinished(Integer i) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName); // thread-0
}
public void execute() {
MyRunnable mr = new MyRunnable(10, this);
Thread t = new Thread(mr);
t.start();
}
}
As you can see, the MyRunnable calls onFinished() when the task is finished. Is there any way I can have the background thread to call this on the main thread? I know I can do similar thing with callables, but right now I want to know if this is possible with runnables,
thank you
Johannes: Take a look at CompletableFuture...
Brendon: I'm more interested in seeing how it work on code
Here's a simplistic implementation that ignores the issue of exceptions. (Pardon me if it's not actually valid Java code.)
class CompletableFuture<ValueType> {
private Object lock = new Object();
private boolean is_completed = false;
private ValueType completed_value;
public synchronized void complete(ValueType v) {
completed_value = v;
is_completed = true;
notifyAll();
}
public synchronized ValueType await() {
while (! is_completed) {
wait();
}
return completed_value;
}
}
The idea is, the client thread creates a CompletableFuture instance, cf, and somehow passes it to the server thread, possibly along with other args that tell the server thread what to do. Then the client thread goes off to do other, unrelated things.
Meanwhile, the server thread does its thing, eventually produces a result, r, and then it calls cf.complete(r).
At some point, the client thread finishes doing whatever else it was doing, and now it needs the result, so it calls cf.await(). Either one of two things happen at that point:
The server already has set the is_completed flag, in which case, the client immediately gets the result, OR
The server has not yet finished, so the client goes in to the wait() loop to wait for it.
When you're looking at application code, you usually never see the part where the client thread creates the Future object or passes it to the other thread. That usually is all taken care of inside the library call when the client submits a task to a thread pool.
In my school's program solutions for multithreading problems and exercises, classes that implement the Runnable interface are usually given a Thread field, which is automatically instantiated in the following example:
protected Thread thr = new Thread(this);
This field is subsequently used as a means of controlling the Thread over which the class itself is instantiated. For example:
public void stop() {
if (thr != null) thr.interrupt();
}
Which is then used to interrupt Thread objects made with the Runnable class.
A full class example, ported directly from an aforementioned solution, is given below:
package hokej;
import java.awt.Color;
public abstract class AktFigura extends Figura implements Runnable {
protected Thread nit = new Thread(this);
private int tAzur;
private boolean radi;
public AktFigura(Scena s, int xx, int yy,
Color b, int t) {
super(s, xx, yy, b); tAzur = t;
}
protected abstract void azurirajPolozaj();
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
if (!radi) wait();
}
azurirajPolozaj();
scena.repaint();
Thread.sleep(tAzur);
}
} catch (InterruptedException ie) {}
}
public synchronized void kreni() {
radi = true; notify();
}
public void stani() { radi = false; }
public void prekini() {
if (nit != null) nit.interrupt();
}
}
My question is this: How does this work?
Shouldn't the Thread field be a separate object from the object made by calling new Thread(class); in other parts of the program (hence the keyword's name - new)?
Or is this simply a special case that the Java interpreter recognizes in a certain way?
Another question would be the viability of this design as a control method. Is there any simpler/more efficient alternative for controlling a Runnable's thread?
How does this work?
The Thread constructor takes a Runnable, Thread implements this interface. this refers to a Thread instance. So, the statement Thread thr = new Thread(this) is valid, but this practice should be avoided.
Is there any simpler/more efficient alternative for controlling a Runnable's thread?
Thread thread = new Thread(new AktFiguraImpl());
thread.start();
You could control a thread by a class specifically designed for that purpose.
class ThreadController {
public ThreadController(Thread thread, AktFigura figura) { ... }
// methods to manipulate the thread
}
In my application, I have two threads given ThreadA and ThreadB. ThreadA is a thread that holds and manipulates some data (the producer) and ThreadB is the corresponding consumer thread that reads from ThreadA (read-only).
I want to achieve that ThreadB informs ThreadA to update the data (which may take some time) and when the data is changed, ThreadB should get/request it from ThreadA. As long as ThreadA has not finished updating the data, ThreadB shouldn't wait but continue his work with the current (old) data he has.
Now my idea was to use the observer pattern to inform ThreadB that ThreadA has finished updating
public class ThreadA implements Runnable {
private boolean sometimesTrue = false;
private int[] someBigArray = new int[XXX];
private synchronized int[] getBigArray() {
return this.someBigArray;
}
private void fireListenerDataChanged() {
for(ThreadAListener l : listeners)
l.notify();
}
private synchronized void updateArray() {
//do some stuff on the array that takes a lot of time
}
#Override
public void run() {
while(true) {
if(sometimesTrue) {
updateArray();
}
}
}
public void doUpdate() {
this.sometimesTrue = true;
}
}
public class ThreadB implements Runnable, ThreadAListener {
private int[] bigDataToWorkOn;
private Thread threadA;
public ThreadB(ThreadA threadA) {
this.threadA = threadA;
}
#Override
public void run() {
//do my stuff with bigDataToWorkOn
if(sometimesTrue) {
threadA.doUpdate();
}
}
public void notify() {
this.bigDataToWorkOn = threadB.getBigArray();
}
}
My main goal was to avoid using some kind of BlockingQueue because then afaik ThreadB would wait with his work until ThreadA passes the data in the queue. The same problem would occur if I would call getBigArray in the while-loop in ThreadB because when ThreadA is currently working in updateArray, ThreadA would be locked and ThreadB would also wait for ThreadA to finish. So is this a proper approach?
This approach could be workable solution, except that fact, that you must mark field sometimesTrue with volatile modifier, if you don't want to have infinite loop inside your run() method of ThreadA.
Futhermore, if you don't want your ThreadA be eating 100% of single core, you have to add some delay into loop inside its run() method:
public void run() {
try {
while(true) {
if(sometimesTrue) {
updateArray();
}
Thread.sleep(100);
}
} catch (InterruptedException e) {
// ... do something with e
}
}
Isn't it possible that notify() in another thread gets called before the wait() in one thread?
It's happening with me.
A client requests a value from a target and waits on a result variable RV.
In case the target is the client itself, I update RV with the correct result and call notify() on RV in another thread.
class EMU {
ResultVar RV;
Address my_address;
ResultVar findValue(String key) {
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV) {
RV.wait();
}
return RV;
}
Runnable Server = new Runnable() {
public void run() {
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0) {
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
RV.notify();
}
}
}
};
}
The problem is that before the requester has completed all the "networking" (sendReqest in the above example) with itself, the result is updated in the result variable. When the requester thread now calls wait(), the program doesn't continue, since notify has already been called.
How can we prevent it?
You check some flag before waiting (in a loop), see the tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
Nothing stops you calling notify on an object that's not being waited by another thread.
It sounds like what you want is a wait only if some condition holds. For example:
synchronized (results) {
while (!results.hasResults()) {
// no results yet; wait for them
try {
results.wait();
} catch (InterruptedException ie) { /* ignore */ }
}
}
I'd strongly recommend not re-inventing the wheel.
Java's Future interface is designed for results that may only arrive later, and the FutureTask class implements this interface.
Have the first thread obtain access to the Future and get the second thread to run the FutureTask, and all of this stuff gets handled for you. You also get timeout support for free.
Use some condition before going to wait() and make sure that condition is thread safe :)
class EMU{
ResultVar RV;
Address my_address;
volatile boolean condition = true;
ResultVar findValue(String key){
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV){
while(condition == true)
{
RV.wait();
}
}
return RV;
}
Runnable Server = new Runnable(){
public void run(){
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0){
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
condition = false;
RV.notify();
}
}
}
};
Let me first break down the code to a minimum reproducable:
public static void main(String[] args) throws Exception {
Object RV = new Object();
new Thread() {
#Override
public void run() {
synchronized (RV) {
RV.notify();
}
}
}.start();
Thread.sleep(1_000);
synchronized (RV) {
RV.wait();
}
}
This method will theoretically never end and the program will never quit. It shall be a dispute if this is a deadlock.
My solution is to create a second lock:
public static void main(String[] args) throws Exception {
Object RV = new Object();
Object lock = new Object();
new Thread() {
#Override
public void run() {
synchronized (lock) {
lock.wait();
}
synchronized (RV) {
RV.notify();
}
}
}.start();
Thread.sleep(1_000);
synchronized (RV) {
synchronized (lock) {
lock.notify();
}
RV.wait();
}
}
Lets inspect what the threads are doing while the main-thread is waiting one second:
The custom Thread will first join the synchronized(lock) block.
Then the lock will causes the custom Thread to wait.
After 1 second the main-thread is joining a RV-synchronization.
The lock gets notified and causes the custom Thread to continue the work.
The custom thread leaves the synchronized(lock) block.
The main thread will RV-wait-lock.
The custom thread notifies the RV-lock to continue.
The program ends.
In the below code, when I execute the producercon class, sometimes the execution stucks, looks like a deadlock. But if i make the get_flag () synchronized then there are no such problems.
I cannot figure out how there can be a problem. the flag can either true or false so only one of the producer or consumer will get into the if statement. After one of them enters the if it will enter the monitor with object r (both are initialized with the same object reference). The only problem which can happen that the r object being modified by the increment_decrement () function call, and the get_flag () reading the flag at the same time, but even then it will not enter the if in that iteration, but it will enter the if block on the next iteration, and even if the first thread did not leave the monitor, it will wait there for it (before the synchronized block).
How, and why is the program halting/hanging if get_flag () is not made synchronized ?
import java.io.*;
class resource
{
private boolean res, flag;
resource ()
{
flag=false;
}
boolean get_flag ()
{
return flag;
}
void increment_decrement (String s,boolean t)
{
res=t;
flag=t;
try
{
System.out.print("\n"+s+":"+res);
Thread.sleep(200);
}
catch(InterruptedException e)
{
}
}
}
class producer implements Runnable
{
resource r1;
Thread t1;
producer(resource r)
{
r1 = r;
t1 = new Thread(this);
t1.start();
}
public void run ()
{
while (true)
{
if(r1.get_flag () == false)
{
synchronized(r1)
{
r1.increment_decrement("Producer",true);
}
}
}
}
public void waitForThread () throws InterruptedException
{
t1.join ();
}
}
class consumer implements Runnable
{
resource r2;
Thread t2;
consumer(resource r)
{
r2 = r;
t2 = new Thread (this);
t2.start();
}
public void run()
{
while (true)
{
if(r2.get_flag () == true)
{
synchronized(r2)
{
r2.increment_decrement("Consumer",false);
}
}
}
}
public void waitForThread () throws InterruptedException
{
t2.join ();
}
}
public class producercon
{
public static void main(String args[])
{
try
{
System.out.print("PRESS CTRL+C TO TERMINATE\n");
resource r = new resource();
consumer c = new consumer(r);
producer p = new producer(r);
c.waitForThread ();
p.waitForThread ();
}
catch(InterruptedException e)
{
}
}
}
Your call to get_flag() is not thread safe nor volatile. This means in the cache of thread 1 it can be true while in the cache of thread 2 it can be false.
You need to make your boolean either volatile or an AtomicBoolean. Right now multiple threads are trying to access the boolean that is in no way synchronized.
This producer/consumer implementation is quite weird.
Neither the producer not the consumer wait for the resource to be in the adequate state, and the resource access is not well protected (the flag should be guarded by some lock to ensure its visibility between threads).
One way to improve on this design would be to use the standart wait/notify system. Another way would be to use a Semaphore in the Resource to ensure only one thread can access the resource at one given time. Finally, you could use a higher-level construct such an java.util.concurrent.SynchronousQueue to pass some data directly from the producer to the consumer.