В чем разница между синхронизированной и статической синхронизацией? - PullRequest
1 голос
/ 08 октября 2009

Для веб-приложения бронирования путешествий, в котором зарегистрировано 100 одновременных пользователей, следует ли бронировать билет и генерировать «номер электронного билета» методом «синхронизировано» или «статически синхронизировано»?

Ответы [ 2 ]

20 голосов
/ 08 октября 2009

Ну, знаете ли вы разницу между статическим методом и методом экземпляра в целом?

Единственное отличие, которое имеет synchronized, состоит в том, что перед тем, как виртуальная машина начнет запускать этот метод, она должна получить монитор. Для метода экземпляра получена блокировка, связанная с объектом, для которого вы вызываете метод. Для статического метода полученная блокировка связана с самим типом, поэтому никакие другие потоки не смогут одновременно вызывать любые другие синхронизированные статические методы.

Другими словами, это:

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

    synchronized void Bar() { ... }
}

равно примерно эквивалентно:

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

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

Обычно я вообще не использую синхронизированные методы - я предпочитаю явно синхронизировать ссылку на частную блокировку:

private final Object lock = new Object();

...

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

Вы не предоставили достаточно информации, чтобы определить, должен ли ваш метод быть статическим или методом экземпляра, или он должен быть синхронизирован вообще. Многопоточность - сложная проблема - я настоятельно рекомендую вам прочитать об этом (через книги, учебные пособия и т. Д.).

3 голосов
/ 08 октября 2009

Ответ Джона покрывает разницу, указанную в заголовке вашего вопроса.

Однако я бы сказал, что ни не должны использоваться для генерации номера билета. Предполагая, что они хранятся в базе данных где-то - база данных должна отвечать за генерацию числа при вставке новой записи (предположительно, с помощью автоинкрементного первичного ключа или чего-то подобного).

В противном случае, если вы должны сгенерировать число в коде Java, я подозреваю, что издержки синхронизации могут быть весьма заметны для 100 одновременных пользователей. Если вы работаете на Java 1.5 или более поздней версии, я бы использовал java.util.concurrent.AtomicInteger, чтобы получить номер билета, который вы можете просто назвать

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();
}

Это дает вам одновременную глобальную уникальность, в которой вы нуждаетесь, гораздо более эффективно, чем синхронизация каждый раз, когда вам нужно целое число.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...