Asynchronous calls are not an implementation detail

Abstract

In this post I want to make clear that the asynchronous behaviour of a method call, is not just an implementation or configuration detail, but should be made explicit in code and documentation.

What is the problem

One of the things I have seen in projects that use multithreading of some sort, is that some method calls are made asynchronous transparently. This means that the caller has no way of knowing if a method call is executed on a different thread or on the thread of the caller..

Origin of the problem

Making a method call asynchronous is quite easy with methods that return void: you could create some sort of asynchronous decorator that executes the real call on a different thread. The caller can return without waiting for the completion of the task, while the thread executes the task at some point in the future. example:

interface Watercooker{
..void activate();
}  

class AsynchronousWatercooker implements Watercooker{
..private final Watercooker cooker;
..public AsynchronousWatercooker(Watercooker cooker){
....this.cooker = cooker;
..}    

..public void activate(){
....Runnable task = new Runnable(){
......public void run(){
........cooker.activate();
......}
....};

....new Thread(task).start();
..}
}

Especially with a powerful framework like Spring it is quite easy to do:

  1. Spring allows unmanaged threads, unlike EJB. So your components are allowed to create threads (you are able to set the resources yourself).
  2. Spring promotes using interfaces rather than classes. So creating an asynchronous decorator is easy. And because classes don’t create instances of dependencies themselves (but rely on Dependency Injection) it is easy to inject an instance of the asynchronous decorator.
  3. Spring has powerful AOP functionality: it is quite easy to create an aspect that makes a call asynchronous.

It doesn’t mean Spring is a bad framework: it is powerful but you still need to design good software.

Why is it a problem

There are a few reasons why transparantly adding asynchronous behaviour could lead to problems:

  1. concurrency issues
  2. different interface requirements
  3. postcondition don’t hold

Why is it a problem: concurrency issues

If data is shared between threads, some sort of concurrency control is required. If the caller is not aware of this, it could lead all kinds of nasty problems like race problems and corrupted data structures.

Why is it a problem: different interface requirements

Interfaces of asynchronous calls are different than interfaces of synchronous calls. The most important one is the difference between exceptions: with a synchronous method call you get an exception that is a consequence of the operation, like CookerIsEmptyException. A asynchronous call typically doesn’t have this kind of exception because the job (in most cases) isn’t executed directly and the caller returns after the task is posted. Asynchronous calls typically have exceptions like TimeOutException (if the job isn’t accepted in a certain amount of time), AlreadyStartedException (if a different thread already has activated the cooker).

Why is it a problem: postconditions don’t hold

Another problem is that you don’t know if postconditions of a call will hold. In case of the Watercooker it could be that you return from the activate method, but the water is still cold: you don’t want to have cold coffee!

Conclusion

That is why the (a)synchronous behaviour of a call should be designed and documented explicitly. In some cases the asynchronous interface will look a lot like the synchronous interface, but there are big differences. Don’t make the mistake by treating them the same, because they are not.

ps:

I want to thank the guys on the concurrency mailinglist for some useful feedback.

About these ads

2 Responses to Asynchronous calls are not an implementation detail

  1. What you are assuming is that aspects are some kind of “magic” thing which is completely transparent to users of code. This is not the case: aspects are a form of extracting code which is not inherently bound to a specific business function, and for instance one may use an asynchronous aspect in order to factor out code of the same kind in a series of classes: this does not mean that I am unaware of when the aspect fires. If your logic is taken to the consequences, then it is aspect oriented programming in itself that you are criticizing, not the specific asynchronicity issue.

  2. pveentjer says:

    I think you misunderstood my point. I don’t have any problem with aspects, I use aspects (in most cases the standard stuff like transactions, performance monitoring, logging).

    My problem is with making method asynchronous and not documenting it. I want to know, if I’m calling a method if the method is asynchronous or not.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: