Run two computations in parallel, and return the results together
From my point of view the implementation is free of race condition because the parallel method does not access any shared variables. All its state is in its local variables so is not shared. 


That is not true. The variable aResult is shared between the thread that called parallel and the thread t1. So there needs to be some synchronization between these two threads, otherwise you run into undefined behaviour.



This low-level JDK memory model gets tricky, so I would try to avoid it as far as possible, i.e. use higher-level abstractions and prefer immutable state.

I suppose the following (still rather low-level) tools (which would solve these issues) are not available for this exercise:


Scala Futures
Java Callables (which return a result instead of having to publish it somewhere)
java.util.concurrent.AtomicReference (which you can use as a thread-safe holder if you have to use Runnable instead of Callable)




As for the specific question: According to the Java Memory Model FAQ


  All actions in a thread happen before any other thread successfully returns from a join() on that thread.


Meaning that after your master thread has joined the first worker thread, it will read the updated value of aResult without that field needing to be volatile.

So your code looks correct to me.

But I had to look this up. Really try to avoid mutable state when multiple threads are concerned.