Делает ли ReadWriteLock синхронизированное ключевое слово ненужным? - PullRequest
7 голосов
/ 08 декабря 2011

Как предлагается в нескольких ответах на этот вопрос:

Как называется эта техника блокировки?

Я реализовал ReentrantReadWriteLock и увидел большое ускорение (я знал, что в одном из моих классов был конфликт блокировки, и использование повторяющейся блокировки помогло ускорить процесс).

Но теперь мне интересно: если внутри класса весь доступ (как чтение, так и запись) осуществляется посредством первой блокировки либо блокировки чтения, либо блокировки записи, означает ли это ключевое слово synchronized больше не будет использоваться в этом классе?

Например, вот один официальный пример Java 1.6, который можно найти по адресу http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

class RWDictionary {
    private final Map<String, Data> m = new TreeMap<String, Data>();
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private final Lock w = rwl.writeLock();

    public Data get(String key) {
        r.lock();
        try { return m.get(key); }
        finally { r.unlock(); }
    }
    public String[] allKeys() {
        r.lock();
        try { return m.keySet().toArray(); }
        finally { r.unlock(); }
    }
    public Data put(String key, Data value) {
        w.lock();
        try { return m.put(key, value); }
        finally { w.unlock(); }
    }
    public void clear() {
        w.lock();
        try { m.clear(); }
        finally { w.unlock(); }
    }
 }

Нет ключевого слова синхронизировать .

Теперь я понимаю, что одна из целей таких блокировок - быть быстрее, чем другие методы (в этом случае быстрее, чем синхронизировать ), но каково техническое объяснение этому?

Заменяет ли использование блокировки чтения-записи в классе в каждом методе get / update ключевое слово синхронизации для этих методов?

1 Ответ

11 голосов
/ 08 декабря 2011

Если вы читаете javadocs на ReadWriteLock и Lock, они специально говорят, что Locks должны предоставлять ту же семантику памяти, что и ключевое слово synchronized:

Все реализации Lock должны применять ту же семантику синхронизации памяти, которая предусмотрена встроенной блокировкой монитора, как описано в Спецификации языка Java, третье издание (17.4 Модель памяти):

(Это от javadoc Lock; ReadWriteLock ссылается на Lock для описания его семантики.)

Итак, да, оно заменяет ключевое слово synchronized. Фактически, вы могли бы заменить каждый synchronized блок в вашем коде на Lock и иметь ту же семантику (и, в зависимости от jvm, возможно, даже небольшое повышение производительности). Но вы бы торговали немного быстрее для скорости больше подробностей, и если вы когда-нибудь забудете разблокировать одну из этих блокировок, вы можете заблокировать вашу программу.

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

...