Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / November 2007

Tip: Looking for answers? Try searching our database.

persistent synchronization signal?

Thread view: 
Tom Forsmo - 20 Nov 2007 21:33 GMT
Hi

I am working on a server where a request is divided into some paralell
tasks. The tasks have to complete in the correct order, even though its
paralellised. For example,  task A and B can start at the same time, but
B can not complete until A is completed, since the last part of B
depends on A's succesfull completion. So I am wondering how can A signal
B abouts its completion. The problem here is twofold 1) that A completes
in only 10-20% of the time of B and 2) that B is the receiver of the
signal sent by A. If I use wait/notify, A will notify long before B has
even gotten to the wait call.

So my question is, does anybody know if there exists a signaling method
that stores a notify signal even though a wait is not yet issued?

I could use some sort of a message queue or even implement a simple
stored_notify_flag()/wait() class myself, but maybe there is another way
of doing it.

Any suggestions?

regards

tom
Patrick May - 20 Nov 2007 22:29 GMT
> I am working on a server where a request is divided into some
> paralell tasks. The tasks have to complete in the correct order,
[quoted text clipped - 10 lines]
> method that stores a notify signal even though a wait is not yet
> issued?

    A JavaSpace may be just what you need.  Check out
http://www.jini.org, and
http://www.jini.org/wiki/Links#Jini_Implementations in particular.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc.  | Large scale, mission-critical, distributed OO
                      | systems design and implementation.
         pjm@spe.com  | (C++, Java, Common Lisp, Jini, middleware, SOA)
Patricia Shanahan - 20 Nov 2007 22:52 GMT
> Hi
>
[quoted text clipped - 20 lines]
>
> tom

The meta-suggestion is to read a tutorial or book on synchronization.
However, here is a pattern for your situation:

Thread A:

synchronized(x){
  set a shared variable to indicate A has completed
  x.notify();
}

Thread B:

synchronized(x){
  while(shared variable indicates A has not completed){
    x.wait();
  }
}

x must refer to a single object.

If B arrives at the synchronized block after A has finished, then the
shared variable will tell it to go ahead without waiting. If B arrives
at the synchronized block before A has finished, then it will go into
the wait, but A will subsequently issue a notify.

Of course, this is only an outline. In real code, you will need to deal
e.g. with interrupts.

Patricia
Daniel Pitts - 20 Nov 2007 23:12 GMT
> Hi
>
[quoted text clipped - 20 lines]
>
> tom
If B requires the result of A, you might look into Future<T> and Executors.
The Java concurrency packages have very useful tools for exactly the
thing you want to do.
Here's a short example:
<SSCCE>
import java.util.concurrent.*;
class ResultA {}
class ResultB {}
class TaskA implements Callable<ResultA> {
   public ResultA call() {return new ResultA();}
}

class TaskB implements Callable<ResultB> {
   Future<ResultA> futureResult;
   public TaskB(Future<ResultA> futureResult) {
      this.futureResult = futureResult;
   }
   public ResultB call() throws Exception {
     doSomeStuff();
     ResultA resultA = futureResult.get();
     doSomeStuffWith(resultA);
     return createResultB();
   }

    private ResultB createResultB() {return new ResultB();}
    private void doSomeStuff() {}
    private void doSomeStuffWith(ResultA resultA) {}
}

public class Main {
   public static void main(String...args) throws Exception {
       ExecutorService executor = Executors.newCachedThreadPool();
       Future<ResultA> futureA = executor.submit(new TaskA());
       Future<ResultB> futureB = executor.submit(new TaskB(futureA));
       futureB.get();
   }
}
</SSCCE>

You should probably read more about concurrency in Java. There are some
good tutorials. There is also an excellent book called Java Concurrency
In Practice
<http://virtualinfinity.net/wordpress/technical-book-recommendations/java-concurr
ency-in-practice/
>

I suggest reading at *least* one of the above.

Hope this helps, and good luck.
Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Hunter Gratzner - 20 Nov 2007 23:12 GMT
> The tasks have to complete in the correct order, even though its
> paralellised. For example,  task A and B can start at the same time, but
> B can not complete until A is completed, since the last part of B
> depends on A's succesfull completion.

Split B into two parts B1 and B2. B1 being the part independent of A.
B2 being the part that requires the input from A (and now from B1,
too). Initialize a CountDownLatch with a count of two. Provide an area
(object) where A and B1 can store their results and B2 can fetch them
from. Start A, B1 and B2 in parallel. Let B2 immediately block on the
CountDownLatch by calling await(). Let A store its result and
countDown() the CountDownLatch when A is done. Let B1 do the same.

Alternatively, do it asymmetric. Initialize a CountDownLatch to one.
Let only A count it down when A is done. Place the await() call at the
end of the B1 code. Place the B2 code directly after the await() call.
Only start A and B1 in parallel. If A is faster than B1 await() will
return immediately and continue executing the B2 code. If A is slower
than B1 the await() call will block until A is done.
Daniel Pitts - 20 Nov 2007 23:14 GMT
>> The tasks have to complete in the correct order, even though its
>> paralellised. For example,  task A and B can start at the same time, but
[quoted text clipped - 15 lines]
> return immediately and continue executing the B2 code. If A is slower
> than B1 the await() call will block until A is done.
Way too complicated. Check out my earlier post. It handles the cases
where A throws an exception. It can also be easily modified to handle
different timeouts on both "A" and "B".

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Eric Sosman - 20 Nov 2007 23:14 GMT
Tom Forsmo wrote On 11/20/07 16:33,:
> Hi
>
[quoted text clipped - 14 lines]
> stored_notify_flag()/wait() class myself, but maybe there is another way
> of doing it.

   You misunderstand wait() and notify() -- don't be ashamed,
because you are not the first to do so and will not be the
last.  The only thing notify() does is to awaken a thread
from a wait() on the designated object, *if* a thread happens
to be sleeping in a wait() at that moment.  If no thread is
sleeping, notify() is a no-op; it does not create a "notified"
state somewhere.

   What B really needs is not a notification, but A's result.
So let's do it this way:

    class B {
       Result fromA = null;
       Object sharedLock = new Object();

       void doIt() {
           doPreliminaryThings();
           synchronized(sharedLock) { // acquire lock
               while (fromA == null) {// any result yet?
                   sharedLock.wait(); // no: unlock, sleep
                                      // ... and re-lock
               }
           }                          // yes: unlock
           doLaterThings(fromA);      // use the result
       }
    }

    class A {
       B theB = ...;

       void doIt() {
           Result result = inventSomething();
           synchronized(theB.sharedLock) { // acquire lock
               theB.fromA = result;        // store result
               theB.sharedLock.notify();   // sleeper, awake!
           }                               // unlock
           // done!
       }
    }

   Notes:

   1) With this pattern it doesn't matter whether A or B
is faster.  If A is faster, it stores its result in fromA
and performs a no-op notify(); B will later find fromA non-
null and will not wait at all.  If B is faster, it finds
fromA null and waits for the situation to change; A eventually
stores to fromA, and in this case its notify() actually wakes B.
Even a dead heat is fine: since one and only one of A and B
can run its synchronized block while the other stalls, that
one effectively "gets there first" and breaks the tie.

   2) A "holder" object like a Collection or an array or
something of your own devising can fill the roles of fromA
and of sharedLock simultaneously.  (Can you see why the
reference variable fromA all by itself won't do the whole
job?)

   3) Observe that B uses `while' and not `if'.  A return
from the wait() method doesn't mean that A *has* called
notify(), only that it *may have* called notify(), so B
must go around and check again -- and possibly go back to
sleep again.  Besides, remember the first principle: B is
not interested in the notification, but in the result, so
it's the presence of the result that's the sure-fire test
for whether to proceed.

Signature

Eric.Sosman@sun.com

Tom Forsmo - 21 Nov 2007 16:40 GMT
>     What B really needs is not a notification, but A's result.

No, in this case I only want notification, i.e. synchronisation. A's
result is not an argument to B, but rather a pre-requisite component for
B to work at all. But your suggestion could have been a posibility if B
needed the result.

>     You misunderstand wait() and notify() -- don't be ashamed,

I am not really that ashamed of not knowing everything in the universe.
Neither should you be.

regards

tom
Eric Sosman - 21 Nov 2007 17:26 GMT
Tom Forsmo wrote On 11/21/07 11:40,:

>>    What B really needs is not a notification, but A's result.
>
> No, in this case I only want notification, i.e. synchronisation. A's
> result is not an argument to B, but rather a pre-requisite component for
> B to work at all. But your suggestion could have been a posibility if B
> needed the result.

   Then the "result" of A is just a boolean: "I'm done."

   Analogy (analogies are faulty, but): I can leave
you voice mail without notifying you that I'm leaving
it -- in fact, that's what makes voice mail useful.
You don't care about the notice "Eric is leaving you
voice mail," but about the state "Eric left you voice
mail."  This is true even if your only action is to
delete the voice mail without listening to it.

Signature

Eric.Sosman@sun.com



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.