Discussions

News: DevX article on using callbacks to isolate concurrency bugs

  1. DevX has published an article called "Using Callbacks to Isolate Concurrency Bugs," by Greg Travis.
    By restricting all object data access to a callback mechanism, a Java server can contain all concurrency issues in a single place, making it much easier for you to see if concurrency constraints have been violated.

    Explaining the benefits of a gatekeeper, he states:
    Implementing a callback-based system requires extra work but it offers a number of benefits.
    Normally, you must acquire certain locks before you can access certain data. Synchronized methods can make this mandatory, but they often aren't enough because the accessing code still has to obey some kind of synchronization protocol. As a system gets larger, you are more and more liable to access the data at the wrong time. Also, just putting synchronization blocks around everything becomes more likely to result in deadlock.
    A callback, on the other hand, cannot access the data until that data is passed to the method, and it cannot access the data after the method is finished. Thus, the period in which the data is available is precisely delineated.
    Furthermore, this mechanism is controlled by the gatekeeper, which can implement any kind of ordering mechanism.

    The technique can be very useful.

    What do you think of it? It's very much a technique grounded in standard Java; would JMS have been more appropriate for throttling access? What issues do you see other techniques having?
  2. java.util.concurrent[ Go to top ]

    I think the new concurrency utilities(java.util.concurrent) address a lot the issues mentioned in this article. I believe Doug Lea has a backward compatible library also.
  3. Gatekeeper?[ Go to top ]

    But who is the keymaster? ;-)
  4. I think the new concurrency utilities(java.util.concurrent) address a lot the issues mentioned in this article. I believe Doug Lea has a backward compatible library also.

    Yes it does, and yes there is a backport. But a Callback is a much friendlyer way of doing things for the average programmer.
  5. reminds me of apartment threading in COM of old.

    Billy

    http://www.billynewport.com
  6. reminds me of apartment threading in COM of old.Billyhttp://www.billynewport.com

    I'm not sure that's a fair comparison. I think you could structure an apartment threading type of model using the concurrency framework as a basis but it's not required nor assumed.

    And anything is better than current J2EE containers' handling of concurrency. Can't get more of an apartment threaded model than a J2EE appserver.
  7. Or use our (IBMs) async beans APIs and take control your self by incorporate what ever kind of threading you need in to your application with a microcontainer of some kind.

    Billy
    http://www.billynewport.com
  8. ... But a Callback is a much friendlyer way of doing things for the average programmer.

    The Executor classes are similar to the Gatekeeper concept and doesn't preclude callbacks. A Callable class that had a callback reference could be triggered on the execution of the task from the executor.
  9. By restricting all object data access to a callback mechanism, a Java server can contain all concurrency issues in a single place, making it much easier for you to see if concurrency constraints have been violated.

    I think there is a context in which the author found this useful which he hasn't been able to abstract out cleanly. In a general sense this is simply likely to many issues.

    a. It is intrusive. The POJOs would need to implement one of Accessor, Mutator or AccessorMutator interfaces
    b. What if a Controller object needs to be able to lock a number of objects (either sequentially or concurrently). It would need to work with a number of gatekeepers and in addition its mutate method might become quite complex due to the necessary instanceof calls and corresponding downcasts (e.g. think of doing (3 + (5 * ( ( 7 - 3) / 2 ) ) ) ) in the context of the example - the mutate method will need to implement all of addition, division, subtraction, and multiplication - in a single method with an if separated by typecasts. I can imagine the mutate method starting to be real big.

    I really think this is a specific pattern for a very specific context. (Which one ? Thats something I havent quite figured out yet).

    Dhananjay
  10. Dhananjay,

    I believe this technique is very intersting, and in a lot of concurrency scenarios it would prevent deadlock situations. This article is just an introductionary sample, and real world examples will of course be more complex.
    a. It is intrusive.
    You are not obliged to implement ths very same interfaces than the author. This one is a generic one, you can specialise the interfaces for your own needs.
    What if a Controller object needs to be able to lock a number of objects (either sequentially or concurrently)
    What about an object seg holding references to the objects you need to obtain references to ?

    Additionally, the GateKeeper can implement a particular scheduling mechanism, to take into account threads priority for instance, an algorithm to detect deadlocks as all locking requests are centralized, etc... Next step would be to directly pass bytecode to the gateKeeper.

    It reminds me of database client server access, where the client asks for the data via a SQL through remote connection, and the SQL is executed on the server itself. It is just more lightweight than embedding a java RDMS instance in your code.

    I wish a basic yet extensible implementation of this would turn into an Apache Commons jar. Sorry i have no time to do it myself. Anybody :o)

    Christian
  11. It's a good approach. Look at the following example:

    A JVM has multiple threads gaining access to a critical section. The JVM also pulls work in from a message transport and each message also accesses the critical section.

    This works fine 'normally' but:

    If the messages get queued up and then delivered in a burst when the JVM is heavily loaded then the following happens:

    The msg loop thread gets a message, locks, accesses, unlocks and loops in a tight loop.

    The msg thread will reacquire the section 99% of the time until it gets preempted between the unlock/lock methods.

    This nails the in JVM threads as they will try to access the section, block because the msg guy has the lock and then be woken up when the msg guy unlocks only to find the msg guy has reacquired and then then back to sleep to be woken up again, and so on. The odds of one of the normal threads getting this lock are pretty low. If there are a lot of threads running then the time the other threads are starved for can be frightening. I've seen a minute or two on a heavily loaded box when this occurs.

    The in JVM threads basically get starved out because of the message burst. Of course, this can happen when any one thread enters a loop like this.

    A gatekeeper approach makes access 'fairer' and prevent this kind of starvation. It's a shame the operating systems or JVMS don't have this kind of logic inside them regardless. Blindly relying on the normal Java synchronized blocks is asking for trouble when the JVMs get heavily loaded.

    Yes, this is from prior experience. :(

    Billy (IBM WebSphere HA architect/WebSphere XD architect)
    http://www.billynewport.com
  12. Billy,

    I 100% agree with you.
    Blindly relying on the normal Java synchronized blocks is asking for trouble when the JVMs get heavily loaded.Yes, this is from prior experience.)http://www.billynewport.com

    I always have to put some yield() in my code to minimize the risk of such a behaviour, what a pitty.

    I am not a pattern expert, but is there any named pattern that would cover this ? If not we could begin writting a "GateKeeper" pattern description and java implementation.

    Any thoughts ?

    As a side question, do JVM's throw some kind of "DeadLockException" when a thread tries to lock an object that is owned by a thread waiting for a lock owned by original thread ? If not, why ?

    Christian
  13. Yield[ Go to top ]

    I'm had mixed results with yield. It sometimes appears to have no effect. I think using a different locking pattern makes more sense than trying to use a simple synchronize and yield combinations for these types of problem.

    Billy
    http://www.billynewport.com
  14. Yield[ Go to top ]

    I'm had mixed results with yield.

    I experienced it also, i meant sleep() :o)

    Christian
  15. Isn't this some kind of custom painfull AOP?

    Regards,
    Horia
  16. Isn't this some kind of custom painfull AOP? Regards,Horia

    Could you elaborate on this ?

    Christian