синхронизация статических методов в одном классе - PullRequest
1 голос
/ 22 июня 2010

У меня есть такой класс:

public class Utils {

    public static void doSomething() {
        // doSomething code
    }

    public static void doSomethingElse() {
        // doSomethingElse code
    }
}

Я хочу, чтобы эти два метода были синхронизированы, но не синхронизированы друг с другом, т.е. никакие два потока не могут обрабатывать метод doSomething () одновременно, никакие два потока не могут обрабатывать doSomethingElse () одновременно, но это нормально для поток для обработки метода doSomething () и другой для одновременной обработки метода doSomethingElse ().

Я реализовал что-то вроде этого:

public class Utils {

    private static final String DO_SOMETHING_LOCK = "DO_SOMETHING_LOCK";
    private static final String DO_SOMETHING_ELSE_LOCK = "DO_SOMETHING_ELSE_LOCK";

    public static void doSomething() {
        synchronized(DO_SOMETHING_LOCK) {
            // doSomething code
        }
    }

    public static void doSomethingElse() {
        synchronized(DO_SOMETHING_ELSE_LOCK) {
        // doSomethingElse code
    }
}

Я вижу, что ответ Скотта Стэнчфилда использует похожий подход:

Как работают синхронизированные статические методы в Java?

но это лучший способ сделать это? Мне кажется немного неуклюжим создание двух объектов только для блокировки - есть ли лучший способ сделать это?

Ответы [ 4 ]

5 голосов
/ 22 июня 2010

Использование строк не очень хорошая идея, потому что та же строка может появиться где-то еще, это будет тот же объект, и вы можете получить зависимости там, где вы их не знаете.Просто сделай

private static final Object DO_SOMETHING_LOCK = new Object();

Остальное в порядке.

1 голос
/ 22 июня 2010

Блокировка интернированного String s является ошибкой.Если вы запустите FindBugs, я думаю, это укажет на вас.Создайте новый экземпляр объекта для блокировки - new Object() или new String("Something informative").Чтобы увидеть что-то полезное в трассировке стека, когда он полностью блокируется, используйте пользовательский класс для задания.

private final Object lock = new Object() { };

или

private static final class MyLock { }
private final Object lock = new MyLock();

На самом деле, обычно лучше создать приватныйвнутренний объект (объекты действительно маленькие - делайте математику), чем открывайте замок через открытый интерфейс.

1 голос
/ 22 июня 2010

Да, это самый простой способ. Хотя объект, который вы блокируете, не должен быть чем-то особенным. Вы можете просто сделать их целыми числами без установленных значений.

0 голосов
/ 22 июня 2010

Ваше решение кажется правильным. Я обычно вижу / использую экземпляры Object как блокировки (вместо Strings), например:

public class Utils {

    private static final Object[] lock = new Object[] { new Object(), new Object() };

    public static void doSomething() {
        synchronized(lock[0]) {
            // doSomething code
        }
    }
    ...
}

Проблема, которую вы пытаетесь решить, связана с ThreadLocal вариантами использования класса.

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