The Source for Java Technology Collaboration
User: Password:



Tom White's Blog

J2SE Archives


Are your beans thread-safe?

Posted by tomwhite on September 21, 2006 at 01:55 PM | Permalink | Comments (27)

[Update: changed wording per comments to fix error.]

Dependency injection is pretty well established these days, with plenty of Inversion of Control containers available to manage your beans. I'm currently reading Java Concurrency in Practice by Brian Goetz et al, which got me thinking about the thread-safety of large object graphs managed by IoC containers.

In most applications I've seen, the common usage pattern is to use dependency injection to wire up your object graph in one go when the application starts. After that the application uses the object graph, and effectively treats it as being immutable. For example, in an application for buying books we might have a BookStore object that is given a BookFinder so it can find whether a particular book is available. The BookFinder is created at the beginning of the application and never changes. It is common to code this using setter injection:

public class BookFinder {

    // BookFinder's business methods...

}

public class BookStore {
    private BookFinder bookFinder;

    public void setBookFinder(BookFinder bookFinder) {
        this.bookFinder = bookFinder;
    }

    // BookStore's business methods which use bookFinder...

}

The problem is that it's not clear that this code is thread-safe. Unless the container publishes the BookStore bean safely then there is no guarantee that other threads will see the value of the BookFinder bean. If this seems weird then that's because it is. To quote Java Concurrency in Practice (p33): "In general, there is no guarantee that the reading thread will see a value written by another thread on a timely basis, or even at all."

Thankfully, this is easy to fix. We can mark the bookFinder instance as volatile to ensure its visibility to other threads:

public class BookStore {
    private volatile BookFinder bookFinder;

    public void setBookFinder(BookFinder bookFinder) {
        this.bookFinder = bookFinder;
    }

    // BookStore's business methods which use bookFinder...

}

Alternatively, we can use constructor injection and final fields. This works because the Java Memory Model makes special guarantees about the safety of final fields.

public class BookStore {
    private final BookFinder bookFinder;

    public BookStore(BookFinder bookFinder) {
        this.bookFinder = bookFinder;
    }

    // BookStore's business methods which use bookFinder...

}

The Future

So could the IoC container providers take steps to ensure that application developers don't have to worry about thread safety in wiring up object graphs? Possibly, although at the time of writing it is less than clear whether the popular containers do or not. Tim Peierls, one of the authors of Java Concurrency in Practice, wrote in a email to me that "Until it's proven safe, I have adopted a rule that all such setter-injected effectively immutable fields must be volatile." He also suggested marking the field with an annotation, such as @WriteOnce, so that when your container's behaviour is clarified it is easy to go through code and remove the volatile modifier.



Counting Characters

Posted by tomwhite on March 22, 2005 at 02:10 PM | Permalink | Comments (4)

During a panel discussion at the 1999 JavaOne conference Bill Joy, talking about the things he didn't like about Java, stated that he "didn't want char to be [a] numerical type". He was outvoted on this one, and as we know the Java char was blessed as a 16-bit numeric primitive type. I don't know whether Joy objected to it being in the numeric type hierarchy (so any char can be cast to an int for example), or whether he didn't like it being a primitive, but what is for sure is that the char's limited width has finally had an impact in the way support for Unicode 4.0 is implemented in Java 1.5.

It was Unicode 3.1 that introduced supplementary characters: characters that require more than 16 bits to represent them. (These characters are rare - think obscure mathematical symbols and languages no longer used outside academia - like Linear B.) Since Java tracks the Unicode standard, the next release - 1.5 - had to solve the problem of how to represent these characters given that a Java char is a 16-bit type. The details of how this was achieved are explained in the excellent article from Sun: Supplementary Characters in the Java Platform, which is required reading for all serious Java programmers. (You might want to read these two introductions first if you're not up on Unicode: Joel Spolsky and Tim Bray.)

For reasons of backward compatibility the fix broke the one-to-one correspondence between Unicode characters and Java chars. A char should now be interpreted as a UTF-16 code unit. The breaking of this correspondence means applications that deal with individual characters may need to be changed - the above article has details. This got me thinking about how you count the number of characters in a piece of text.

Continue Reading...



The Java Language Specification, 3rd Edition

Posted by tomwhite on February 28, 2005 at 02:16 PM | Permalink | Comments (6)

There was no fanfare, in fact it's not even linked to from the JDK 1.5 documentation, but the third edition of the Java Language Specification is available for "maintenance review". I only found it because I wondered if a new version of the JLS had been produced for 1.5, and went out looking for it. The changes are only "proposed" changes - it is odd that they didn't go final with the release of 1.5.0 - and there's even a language change from 1.4 in there too (assertions). Presumably it will be finalised when the book is printed.

There have been some big changes in Java recently so it's good that the JLS has had a bit of work done on it as it was looking a bit forgotten. Here's a list of the new language features by chapter:

  • Chapter 3, Lexical Structure - Unicode supplementary character support
  • Chapter 4, Types, Values and Variables - Generics
  • Chapter 5, Conversions and Promotions - Autoboxing/Unboxing
  • Chapter 7, Packages - Static Import
  • Chapter 8, Classes - Varargs and Typesafe Enums
  • Chapter 9, Interfaces - Annotations
  • Chapter 14, Blocks and Statements - Enhanced for Loop and Assertions
  • Chapter 17, Threads and Locks - The Revised Memory Model (almost completely re-written)

It's probably worth a re-read.





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds