Friday, 25 March 2011

Thread-safe and lock free variables

The java.util.concurrent.atomic package contains classes which aim to ease concurrency concerns in multithreaded applications. They offer better performance than using synchronisation because its operations on fields do not require locking.

The classes AtomicBoolean, AtomicInteger, AtomicLong and AtomicReference enable the primitives boolean, int, long and an object reference to be atomically updated. They all provide utility methods like compareAndSet which takes an expected value and the update value and returns false if the expected value doesn't equal (==) the current value. The AtomicInteger and AtomicLong classes also provide atomic pre and post decrement/increment methods like getAndIncrement or incrementAndGet.

An example use of one of the 'scalar' atomic classes is shown below:

public class IdentifierGenerator {

    private AtomicLong seed = new AtomicLong(0);

    public long getNextIdentifier() {
        return seed.getAndIncrement();
    }

} 


The int and long primitives, and also object references can be held in arrays where the elements are atomically updated namely AtomicIntegerArray, AtomicLongArray and AtomicReferenceArray.

There also exists field updater classes namely AtomicIntegerFieldUpdater, AtomicLongFieldUpdater and AtomicReferenceFieldUpdater. With these classes you can still use the methods on the class but use the updater class to manage the field that requires atomic access via methods like compareAndSet. Note that because of this, atomcity isn't guaranteed.

These are abstract classes and the below (contrived!) example shows how an instance would be created:

    public void setBalance(Customer customer, int exisitngBalance, 
        int newBalance) {

        AtomicIntegerFieldUpdater<Customer> balanceAccessor 
            = AtomicIntegerFieldUpdater.newUpdater(
        Customer.class, "balance"); 
        balanceAccessor.compareAndSet(customer, exisitngBalance, newBalance);

    }

Thursday, 24 March 2011

Weak and Soft References and the Garbage Collector

Java uses the Garbage Collector to manage memory. It does this by freeing up memory no longer needed by the application ie memory used by objects that are not referenced anymore, in other words, objects that are ‘unreachable’.

Typically, objects are strongly referenced so they remain in memory until no longer reachable,

Customer customer = new Customer();

but there are certain scenarios where you’d want to keep references to objects and also allow them to be garbage collected if needs be eg when memory is at a premium. A solution to this problem is to use Reference Objects.

There are three concrete implementations of the java.lang.ref.Reference<T> class: WeakReference, SoftReference and PhantomReference.

Objects held only by a WeakReference are deemed to be weakly reachable and are therefore eligible for garbage collection. An example of creating a WeakReference is below:

WeakReference<Customer> weakCustomer = new
    WeakReference<Customer>(customer);

To obtain the customer object held by the weak reference, you would call weakCustomer.get(). This will always return the customer object unless the garbage collecter has deemed the object to be weakly reachable and therefore has freed it from memory. In that case, calling the get method will return null;

If you want to hold a collection of the objects that can be garbage collected, then you can use a WeakHashMap. This collection uses weak references as keys, so when the key becomes garbage collected, the entry for that key in the WeakHashMap gets removed. This collection class isn’t synchronized so use Collections.synchronizedMap for a synchronized version, but be beware that whether synchronized or not, the size of the Map may decrease over time as the garbage collector removes entries, so an iterator may return ConcurrentModificationException.

A SoftReference holds onto the object more strongly than a WeakReference and if memory is not a problem the garbage collector will not free up the memory used by objects held by a soft reference.

You can also create another type of reference to an object, a PhantomReference. Calling the get method on such a reference will always return null though thereby preventing you from ‘resurrecting’ the object.  It’s only real use is when you pass a ReferenceQueue into the PhantomReference constructor.

You can pass a ReferenceQueue into the constructor of all the Reference types. It enables you to keep track of objects which have been garbage collected. When the object’s finalize method is called, the object will be placed on the reference queue. This process is called ‘enqueuing’. You then know when it was removed from memory.

In the case of a PhantomReference, passing in a null ReferenceQueue would be a pointless exercise, rendering the creation of the PhantomReference useless.