JMM: Cache invalidation vs happens before rules

February 11, 2008

In the last 2 month I have had 2 discussion with other developers about the Java Memory Model (JMM) about some visibility issues and after some discussion I figured out they were still using the ‘cache invalidation’ approach instead of the happens before model the JMM is expressed in. One of the problems with the former approach is that according to that approach, the following example doesn’t contain a visibility problem.

final Object a = new Object();
final Object b = new Object();
int x = 0;

void foo(){
	synchronized( a ){
		x = 10;
	}
}

void bar(){
	synchronized( b ){
		println( x );
	}
}

According to the cache invalidation approach, the cache is invalidated as soon as the lock(b) is acquired, forcing all changes made prior to the release of lock(a), to become visible in the current thread. It doesn’t matter if the locks are not the same. According to the JMM and the monitor rule (one of the happens before rules), there is no happens before relation between the write of x and the read of x, because the locks are not the same. So according to that model there is a visibility problem.

Conclusion? Stop reasoning about caches/cache-invalidations and start reasoning with happens before rules. That is the easiest way to predict what could happen.

Advertisements

Are you dealing with the RejectedExecutionException?

February 6, 2008

One of the things I encounter from time to time is the missing handling of the RejectedExecutionException (thrown by the Executor). This exception can be thrown when the executor:

  1. is shutting down. When it is shutting down, you don’t want it to execute accept new task: the shutdown should have a higher priority than the acceptance of new tasks.
  2. the executor doesn’t want to accept the task. If you are using a bounded BlockingQueue as workqeue in the ThreadPoolExecutor (bounded = good, makes your system degrade gracefully) and the queue is full, the Executor doesn’t block until the task can be placed (this is something not all developers realize), but rejects the tasks by throwing the RejectedExecutionException.

So the RejectedExecutionException is a ‘normal’ situation that could happen in a healthy system. So make sure you are dealing with the RejectedExecutionException. If you don’t deal with this situation, unwanted behavior, like disappearance of tasks, could be the consequence.