Search code examples
javasynchronizationlockingrunnablecallable

Fastest synchronization technique


Following is a rather common scenario of accessing a common resource, either in a sequential (single-threaded) or a concurrent (multi-threaded) way, for which the fastest technique is needed.

More specifically (see sample source code below), a Manager class creates some instances of a Runnable (or Callable) class (Handler) with a common resource (a Store object). The Manager class is actually subclassed and its execute() method overridden to run the handlers sequentially in the same thread, or in multiple threads (e.g., via an ExecutorService), depending on the subclass implementation.

My question is, what would be the fastest (less overhead) way of synchronizing access to the shared Store object inside the run (or call()) method of each Handler object, especially taking into account that, for single-threaded access, that synchronization is redundant (but has to be there, because there are also multi-threaded Manager subclass implementations).

Would, for instance, a synchronized (this.store) {this.store.process()} block be better than, say, using a Lock object from java.util.concurrent, before and after calling this.store.process()? Or would a separate synchronized method inside Handler for each store access be faster? For example, instead of calling this.store.process(), run something like

private synchronized void processStore()
{
    this.store.process();
}

Following is the (sample) source code.

public class Manager
{
    public Manager()
    {
        Store store = new Store(); // Resource to be shared
        List<Handler> handlers = createHandlers(store, 10);

        execute(handlers);
    }

    List<Handler> createHandlers(Store store, int count)
    {
        List<Handler> handlers = new ArrayList<Handler>();

        for (int i=0; i<count; i++)
        {
            handlers.add(new Handler(store));
        }

        return handlers;
    }

    void execute(List<Handler> handlers)
    {
        // Run handlers, either sequentially or concurrently 
    }
}

public class Handler implements Runnable // or Callable
{
    Store store; // Shared resource

    public Handler(Store store)
    {
        this.store = store;
    }

    public void run() // Would be call(), if Callable
    {
        // ...
        this.store.process(); // Synchronization needed
        // ...
        this.store.report();  // Synchronization needed
        // ...
        this.store.close();   // Synchronization needed
        // ...
    }       
}

public class Store
{
    void process() {}
    void report()  {}
    void close()   {}
}

Solution

  • In general: CAS synchronization < synchronized < Lock in terms of speed. Of course this will depend on the degree of contention and your operating system. I would suggest you try each and determine which is the fastest for your need.

    Java also performs lock elision to avoid locking on objects that are only visible to one thread.