Какая-либо причина НЕ хлопнуть 'синхронизируемое' ключевое слово везде?

Ваша проблема просто в том, что вы добавляете аргумент template внутри directive, а также добавляете разрешающий тег шаблона с именем <easydialog> в ваш фактический HTML-шаблон. У вас есть выбор, один или другой.

12
задан Lucky 11 June 2009 в 03:26
поделиться

9 ответов

Конечно - производительность. У мониторов есть своя цена.

Ответ - ни удаление, ни добавление синхронизации случайным образом. Лучше почитать что-нибудь вроде книги Брайана Гетца «Java Concurrency In Practice» или книги Дуга Ли «Java Threads», чтобы понять, как это сделать правильно. И, конечно, хорошо изучите новые параллельные пакеты.

Многопоточность - это намного больше, чем ключевое слово synchronized.

27
ответ дан 2 December 2019 в 02:49
поделиться

Если вы синхронизируете без разбора, вы также рискуете создать тупиковую ситуацию .

Предположим, у меня есть два класса, Foo и Bar , у обоих есть синхронизированный метод doSomething () . Предположим далее, что у каждого класса есть синхронизированный метод, принимающий экземпляр другого класса в качестве параметра.

public class Foo {

    synchronized void doSomething() {
        //code to doSomething
    }

    synchronized void doSomethingWithBar(Bar b) {
        b.doSomething();
    }

}

public class Bar {

    synchronized void doSomething() {
        //code to doSomething
    }

    synchronized void doSomethingWithFoo(Foo f) {
        f.doSomething();
    }
}

Вы можете видеть это, если у вас есть экземпляр Foo и экземпляр Bar ], оба пытаются выполнить свои методы doSomethingWith * друг для друга одновременно, может возникнуть тупик.

Чтобы принудительно установить взаимоблокировку, вы можете вставить сон в оба метода doSomethingWith * (используя Foo в качестве примера):

synchronized void doSomethingWithBar(Bar b) {
    try {
        Thread.sleep(10000);
    } catch (InterruptedException ie) {
        ie.printStackTrace();
    }

    b.doSomething();
}

В вашем основном методе вы запускаете два потоки для завершения примера:

public static void main(String[] args) {
    final Foo f = new Foo();
    final Bar b = new Bar();
    new Thread(new Runnable() {
        public void run() {
            f.doSomethingWithBar(b);
        }
    }).start();

    new Thread(new Runnable() {
        public void run() {
            b.doSomethingWithFoo(f);
        }
    }).start();
}
36
ответ дан 2 December 2019 в 02:49
поделиться

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

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

13
ответ дан 2 December 2019 в 02:49
поделиться

Точка производительности уже была указана.

Также помните, что все потоки получают разные копии стека. Следовательно, если метод использует только переменные, созданные внутри этого метода, и нет доступа к внешнему миру (например, дескрипторам файлов, сокетам, соединениям с БД и т. Д.), Тогда нет возможности возникновения проблем с потоками.

7
ответ дан 2 December 2019 в 02:49
поделиться

Просто это почти наверняка замедлит работу.

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

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

2
ответ дан 2 December 2019 в 02:49
поделиться

Намного лучше, чем помещать везде synchronized , - это тщательно продумать, какие инварианты нужны вашим классам, а затем синхронизировать ровно столько, чтобы гарантировать эти инварианты. Если вы чрезмерно синхронизируете, вы создаете два риска:

  1. тупик
  2. проблемы жизнеспособности

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

Если вы хотите использовать ключевое слово везде в целях безопасности, я рекомендую использовать final вместо synchronized . : ) Все, что вы можете сделать final , способствует лучшей поточной безопасности и упрощает рассуждения о том, какие инварианты должны поддерживаться блокировками. В качестве примера предположим, что у вас есть этот тривиальный класс:

public class SimpleClass {
    private volatile int min, max;
    private volatile Date startTime;
    // Assume there are many other class members

    public SimpleClass(final int min, final int max) {
        this.min = min;
        this.max = max;
    }
    public void setMin(final int min) {
        // set min and verify that min <= max
    }
    public void setMax(final int max) {
        // set max and verify that min <= max
    }
    public Date getStartTime() {
        return startTime;
    }
}

С указанным выше классом при установке минимального или максимального значения вам необходимо выполнить синхронизацию. Код выше не работает. Какой инвариант есть у этого класса? Вы должны убедиться, что min <= max всегда, даже когда несколько потоков вызывают setMin или setMax .

Предполагая, что это большой класс со многими переменными, и вы синхронизируете все, тогда, если один поток вызывает setMin , а другой поток вызывает getStartTime , второй поток будет без необходимости заблокирован до тех пор, пока setMin не вернется. Если вы сделаете это с классом с большим количеством членов,

6
ответ дан 2 December 2019 в 02:49
поделиться

Допустим, у вас есть этот пример


synchronized (lock){
    doSomething();
}

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

1
ответ дан 2 December 2019 в 02:49
поделиться

Вы не должны, и вам, вероятно, придется пересмотреть свой дизайн. По моему опыту, синхронизация на этом уровне просто не масштабируется. Это может решить ваши непосредственные проблемы, но не поможет исправить вашу общую целостность приложения.

Например: даже если у вас есть «синхронизированная» коллекция, один поток может захотеть вызвать два «синхронизированных» метода за один раз. , но не хотите, чтобы другой поток видел промежуточный результат. Таким образом, любой вызывающий мелкозернистый «синхронизированный» API должен сам знать об этом, что сильно ухудшает (программистское) удобство использования этого API.

Для начала лучше всего использовать рабочие потоки. Изолируйте определенные длительные задачи, чтобы отдельные потоки принимали один блок неизменяемого ввода и - по завершении - ставили результат в очередь в основной поток ' s очередь сообщений (это, конечно, должно быть синхронизировано). Основной поток может опрашивать или явно ждать сигнала, если ему больше нечего делать. Конкретные детали зависят от ваших требований к производительности и дизайна приложения.

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

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

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

2
ответ дан 2 December 2019 в 02:49
поделиться

Если производительность не является большой проблемой, почему бы вам не использовать один поток, а затем вы можете безопасно удалить все синхронизированные «Если вы синхронизируете все, вы фактически достигли того же самого, что только один поток может делать что угодно, но гораздо более сложным и подверженным ошибкам способом.

Спросите себя, почему вы используете более одной ветки?

0
ответ дан 2 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: