Tuesday, January 22, 2008

Stupid JVM Tricks - Read locks from just synchronized

I bet if you asked someone in an interview what the synchronized block in Java does, they are likely to answer something along the lines of "protected sections" of code, if you are lucky they might answer with a deeper technical understanding, with terminology such as "atomicity," "mutual exclusion," "monitors," and the like.

I will further bet that if you asked if it's possible for Java's synchronized keyword to produce read lock semantics (e.g. concurrent access), you would hopefully get a resounding no. Ok, well, if your interviewee is clever enough, they might tell you that you could build a read lock mechanism, but that synchronized itself only provides you with write lock semantics - that is to say, mutual exclusion.

So if I ask you the very same question - what's your answer?

Mine is ... YES!

Let me show you how. First, here's my code (in a file called Main.java):

public class Main implements Runnable
{
public static final Main instance = new Main();

public void run()
{
enterMonitor();
}

public synchronized void enterMonitor()
{
System.out.println("I'm in the synchronized block"); System.out.flush();
try { Thread.currentThread().sleep(5000); }
catch (InterruptedException ie) { System.out.println("Interrupted"); }
}

public static void main(String[] args) throws Exception
{
for (int i = 0; i < 10; i++) {
new Thread(instance).start();
}
}
}


And here's my output:


I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block
I'm in the synchronized block


(Note that all statements above were printed at the same time, not serially)

Now, I hope you are wondering how I did that. If not, this post really isn't for you. If you are, ok, ok, I admit it. Vanilla synchronized really can't give you read semantics, but with a bit of sleight of hand, Terracotta can do it for you.

The way I made the above output happen is that I configured Terracotta to treat the synchronized block as a read lock. The rest is simple - Terracotta manages the locking, and since it was told to make the particular lock in question a read lock, lo and behold, I was able to get fully concurrent access to the code inside the synchronized block.

I know what you are thinking now - holy synchronized block batman! That could be a disaster for code that wasn't expecting to be run concurrently! And you'd be right - except Terracotta is smarter than that. Let's suppose I had accidentally surrounded some code that made field updates (performing a write) to my object with a synchronized block, and told Terracotta to make that into a read lock. If I do that, and run the code with Terracotta, it will tell me (by throwing an Exception) at the point of modification that I made a mistake and my code was mistakenly trying to make an update to an object under a read lock. In other words, no, using read locks with Terracotta is not dangerous at all, and it can really boost the performance of your app.

Update: To see how simple this is, let me post the relevant bit of Terracotta config that converts the above synchronized into a read lock:
<locks>
<autolock>
<method-expression>void Main.enterMonitor()</method-expression>
<lock-level>read</lock-level>
</autolock>
</locks>


For all the details, see my full write-up in the Terracotta Cookbook - a really great place to see simple examples that demonstrate the power of Terracotta.

Thursday, January 17, 2008

In today's world, what is the role of the Application Server?

Undoubtedly, you noticed a few changes in the Enterprise world:

1) Sun bought MySQL for a reported $1B

2) Oracle bought BEA for a reported $8.2B

I've already been asking this question to various individuals, with these recent announcements it occurred to me that I'd be interested in what you, the blog reading public have to say.

My question is this:

Given the likes of Spring and Hibernate, how do people consume the Application Server? Is it all you can eat with JEE still delivering on the promise of writing business logic and letting the App server deal with the infrastructure? Or do things like Spring, Hibernate, JPA etc. change the game - are people choosing a best of breed approach, with lightweight frameworks (Spring, ActiveMQ, Hibernate etc) and lightweight containers (Tomcat, Jetty etc) allowing developers to build the stack they need, and no more?

How do the acquisitions mentioned above change the game? Is BEA still delivering value, or is the App server market completely commoditized?

I would love to hear your comments!