‘Synchronize’ Gotcha: The Thread Locks The Object, Not The Method!

watch-cogs-wheels-parts

This is one of the fundamental aspects of Java synchronisation, but I have seen so many people get it wrong when I’m interviewing them. It’s very simple, but slightly contrary to how you might think synchronisation works.

So let’s take this code:

package com.example.shane.myapplication;

/**
 * Created by shane on 27/12/16.
 */
public class Foo {
 
 public synchronized void methodA(){
 /* Do potentially thread-unsafe stuff here */
 }

 public synchronized void methodB(){
 /* Do more potentially thread-unsafe stuff here*/
 }
 
}

So far so good; if a thread accesses methodA, any other threads will have to wait there turn before they too can access that method (assuming they are all using the same instance of the class!).

But what about if another thread wants to access methodB while the first thread is still in methodA? They are separate methods, right? And as long as there are not shared objects being manipulated by both methods, you should be able to safely access methodB with the second thread without having to wait for the first thread to finish it’s business with methodA.

Or so you’d think….and you’d be wrong!

Java synchronisation works via threads acquiring locks. If one thread has a lock, another thread can’t acquire it. Later versions of java have explicit Lock objects, but the synchronisation keyword works using implicit locks behind the scenes. When you enter a synchronised method, the thread acquires a lock for the whole object (not just that method).

This means that if a thread accesses a synchronised method (thus acquiring the underlying objects associated lock), any other synchronised methods in the object will also be locked, and other threads will need to wait to access them. In my above example, methodA is locked by the first thread, but so is methodB.

It’s very simple once you understand it, but it’s one of those ‘gotchas’ that doesn’t get picked up on as often as it should (probably as writing multi-threaded code isn’t as in demand as it used to be, plus synchronize is arguably outdated now, what with all the modern Java concurrency packages).

It’s still important to know, though, as if you are using synchronize (or are updating legacy code), you could create a very nasty and obscure deadlock.

 

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s