views:

1076

answers:

2

For a travel booking web application, where there are 100 concurrent users logged in, should ticket booking and generating an "E-Ticket Number" be implemented by a "synchronized" or a "static synchronized" method?

+7  A: 

Well, are you aware of the difference between a static method and an instance method in general?

The only difference that synchronized makes is that before the VM starts running that method, it has to acquire a monitor. For an instance method, the lock acquired is the one associated with the object you're calling the method on. For a static method, the lock acquired is associated with the type itself - so no other threads will be able to call any other synchronized static methods at the same time.

In other words, this:

class Test
{
    static synchronized void Foo() { ... }

    synchronized void Bar() { ... }
}

is roughly equivalent to:

class Test
{
    static void Foo()
    {
        synchronized(Test.class)
        {
            ...
        }
    }

    void Bar()
    {
        synchronized(this)
        {
            ...
        }
    }
}

Generally I tend not to use synchronized methods at all - I prefer to explicitly synchronize on a private lock reference:

private final Object lock = new Object();

...

void Bar()
{
    synchronized(lock)
    {
        ...
    }
}

You haven't provided nearly enough information to determine whether your method should be a static or instance method, or whether it should be synchronized at all. Multithreading is a complex issue - I strongly suggest that you read up on it (through books, tutorials etc).

Jon Skeet
sacsha
Both your question and this comment that repeats it make no sense. if Jon Skeet's excellent answer did not fulfill your needs, please rephrase your question.
SingleShot
Out of curiosity: How is it "roughly" equivalent? I was under the impression that the effective execution is the same (even though "synchronized" on the method is turned into a flag instead of some bytecode instructions (which the synchronized block is turned into)).
Joachim Sauer
@Joachim: I have a **feeling** that the JVM makes sure that the thread doesn't even enter a synchronized method *at all* until it's acquired the lock - so if it's deadlocked, a stack trace would show the calling method at the top level. With the synchronization *in* the method, that method would be at the top. I could be wrong though - and there could be other subtleties I'm not aware of.
Jon Skeet
+3  A: 

Jon's answer covers the difference hinted at in your question title.

However, I would say that neither should be used for generating a ticket number. On the assumption that these are being stored in a database, somewhere - the database should be responsible for generating the number when you insert the new record (presumably by an autoincrementing primary key, or something similar).

Failing that, if you must generate the number within Java code, I suspect that the synchronisation overhead might be quite noticeable with 100 concurrent users. If you are running on Java 1.5 or later, I'd use a java.util.concurrent.AtomicInteger to get the ticket number, which you can simply call as

private static final AtomicInteger ticketSequence;

static
{
    final int greatestTicket = getHighestExistingTicketNumber(); // May not be needed if you can start from zero each time
    ticketSequence = new AtomicInteger(greatestTicket + 1);
}

public /*static*/ int getNextTicketNumber()
{
    return ticketSequence.incrementAndGet();
}

This gives you the concurrent global uniqueness you need in a much more efficient fashion than synchronizing every time you need an integer.

Andrzej Doyle