Skip to main content

Blocks and Locks

Posted by mason on September 8, 2006 at 10:14 AM PDT

Code block, in a nutshell, are basically just "lambda" functions (also known as closures in many other languages, most apropos might be Groovy) that are tied directly to a single method call. The canonical case is the way Ruby does array iterators:


[1, 2, 3].each { |i| puts "the value is #{i}" }

In this case the code block "{ |i| ... }" is passed to the method "each". This method calls the block over and over again, each time handing it the next value in the array.

This isn't exactly possible in Java, but something close is possible using anonymous classes and specialized interfaces. Consider the following class:


public class EachArray<T> extends ArrayList<T> {
    public static interface Each<E> { public void each(E i); }        
    public void each(Each<T> each) { for (T t : this) { each.each(t); } }
}

This class is rougly the same as the ruby version of an array. To use it you would have to implement a new Each object, but it could be created as an anonymous class, giving you something like this:

EachArray<Integer> a = new EachArray<Integer>();
...
a.each(new Each<Integer>() {
    public void each(Integer i) {
        //do something with i
    }
});

It's actually a bit verbose, but it does give you the idea... But it's verbosity begs the question, how is this actually as or more useful than just using a normal iterator? In ruby it makes sense, as the language supports a much more concise syntax, but when it gets this wordy, is there all that much value?

The example above isn't particularly nice, it's just a quick way to show you how it's done, however a more readily useful example may look like this:


public abstract class CriticalBlock {
    public CriticalBlock(ReentrantLock lock) { exec(lock); }
    protected abstract void critical() throws Throwable;
    private void exec(ReentrantLock lock) {
        try {
            lock.lockInterruptibly();
            critical();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }
}

This will give you a very nice way to both lock important secions of code inside of a lock and also inform other developers how important the secion is. Furthermore, the code doesn't look too different from a synchronized block (but doesn't have the problems associated with syncronization):


ReentrantLock syncPoint = new ReentrantLock();
new Thread() {
    public void run() {
        new CriticalBlock(syncPoint) {
            public void critical() {
                //important section    
            }
        }    
    }
}.start();
new Thread() {
    public void run() {
        new CriticalBlock(syncPoint) {
            public void critical() {
                //second important section    
            }
        }    
    }
}.start();

If you look close, you may see the very interesting additional bit of value, perhaps for some people the most important, of building objects like the above: Anyone using the cirical block is guaranteed to use the lock/unlock pair correctly. Nobody can accedentally forget to call "unlock" after the opertation is complete. this style of coding allows you to write the complex or otherwise vital, but repetative bit of logic once as a utility class, and everyone using the class is guaranteed not to flub the implementation, even, for example, if they didn't know how to use the complex bits properly.

If you are interested in how this could be useful in a more complex setting, my next entry will be on double checked locks and will use code blocks to simplyfy the process. In the meantime, play with the concept on your own and see how the paradigm suits you. There are other, more complex trics to get around some of the uglier verbosity, but if you can stand an extra indent, or can stomach a squashed line or two, it may be a solution to many conundrums you have been facing. and who knows, if it catches on, maybe Sun will include true code-block syntax some day.

Related Topics >>