Synchronized as volatile replacement: part I

I was looking at the source code of Quartz (the SimpleThreadpool to be specific) and I noticed that synchronized blocks are used to access a single variable (read/write) instead of declaring the variable volatile.

//write: runnable is a object field.
synchronized(this) {
	runnable = null;

//read: run is an object field, shouldRun is a local variable.              
synchronized(this) {
	shouldRun = run;

The main purpose of these synchronized blocks, next to preventing reordering problems, is the prevent visibility problems: each reading thread that uses some lock, will see the most recently written value, written under the same lock. If the synchronized blocks are missing, one thread doesn’t need to see the changes made by another thread, because values can be stuck in the cache of a cpu for example. So synchronized blocks are a legit way to let threads exchange information.

But this can just as easily be achieved by declaring the variable volatile because the lock.release/lock.acquire (monitor lock rule) has the same JMM properties as a volatile.write and a (the volatile variable rule). So if there are no invariants that can break by early publication of some state value, I prefer volatiles over synchronized blocks for publication for the following reasons:

  1. once declared volatile, each variable access will be protected. With synchronized locks it is easy to forget because you need to rely on a convention (that often isn’t documented or well understood).
  2. volatiles are lightweight, and won’t lead to Operating System calls unlike locks. Although JVM optimizations like biased locking and adaptive spin locking can reduce the actual number of Operating System calls. For more information about lock optimizations you could have a look at the following article on InfoQ article written by Jeroen Borders, a colleague.

In some cases you can even combine volatiles with locks: if the early publication of the variable doesn’t break invariants, but a change to that variable needs to be done atomic in combination with others.

In the next blogpost I will explain that synchronized blocks are a little bit more strict than volatiles variables.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: