Synchronizing issue: I want the main thread to be run before another thread but it sometimes doesn´t

Posted by Rox on Stack Overflow See other posts from Stack Overflow or by Rox
Published on 2012-09-15T09:34:26Z Indexed on 2012/09/15 9:37 UTC
Read the original article Hit count: 401

I have done my own small concurrency framework (just for learning purposes) inspired by the java.util.concurrency package. This is about the Callable/Future mechanism. My code below is the whole one and is compilable and very easy to understand.

My problem is that sometimes I run into a deadlock where the first thread (the main thread) awaits for a signal from the other thread. But then the other thread has already notified the main thread before the main thread went into waiting state, so the main thread cannot wake up.

FutureTask.get() should always be run before FutureTask.run() but sometimes the run() method (which is called by new thread) runs before the get() method (which is called by main thread). I don´t know how I can prevent that.

This is a pseudo code of how I want the two threads to be run.

//From main thread:
Executor.submit().get() (in get() the main thread waits for new thread to notify)
         ->submit() calls Executor.execute(FutureTask object)
                                   -> execute() starts new thread
                                                 -> new thread shall notify `main thread`

I cannot understand how the new thread can start up and run faster than the main thread that actually starts the new thread.

Main.java:

public class Main {
    public static void main(String[] args) {
        new ExecutorServiceExample();
    }

    public Main() {

        ThreadExecutor executor = new ThreadExecutor();
        Integer i = executor.submit(new Callable<Integer>() {
            @Override
            public Integer call() {
                return 10;
            }
        }).get();
        System.err.println("Value: "+i);
    }
}

ThreadExecutor.java:

public class ThreadExecutor {

    public ThreadExecutor() {}

    protected <V> RunnableFuture<V> newTaskFor(Callable c) {
        return new FutureTask<V>(c);
    }

    public <V> Future<V> submit(Callable<V> task) {
        if (task == null) 
            throw new NullPointerException();
        RunnableFuture<V> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

    public void execute(Runnable r) {
        new Thread(r).start();
    }
}

FutureTask.java:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FutureTask<V> implements RunnableFuture<V> {
    private Callable<V> callable;
    private volatile V result;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public FutureTask(Callable callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
    }

    @Override
    public void run() {
        acquireLock(); 
        System.err.println("RUN"+Thread.currentThread().getName());
        V v = this.callable.call();
        set(v);
        condition.signal();
        releaseLock();
    }

    @Override
    public V get() {
        acquireLock();
        System.err.println("GET "+Thread.currentThread().getName());
        try {
            condition.await();
        } catch (InterruptedException ex) {
            Logger.getLogger(FutureTask.class.getName()).log(Level.SEVERE, null, ex);
        }
        releaseLock();
        return this.result;
    }

    public void set(V v) {
        this.result = v;
    }

    private void acquireLock() {
        lock.lock();
    }
    private void releaseLock() {
        lock.unlock(); 
    }
}

And the interfaces:

public interface RunnableFuture<V> extends Runnable, Future<V> {
    @Override
    void run();
}


public interface Future<V> {
    V get();
}


public interface Callable<V> {
    V call();
}

© Stack Overflow or respective owner

Related posts about java

Related posts about multithreading