В чем разница между синхронизированными полями и ReadWriteLocks? - PullRequest
0 голосов
/ 02 апреля 2019

Просто хочу узнать, чем отличаются приведенные ниже коды, выполняющие те же функции

Код 1:

    class ReadWriteCounter {
    ReadWriteLock lock = new ReentrantReadWriteLock();

    private Integer count = 0;

    public Integer incrementAndGetCount() {
        lock.writeLock().lock();
        try {
            count = count + 1;
            return count;
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Integer getCount() {
        lock.readLock().lock();
        try {
            return count;
        } finally {
            lock.readLock().unlock();
        }
    }
}

Код 2:

class ReadWriteCounter {

private Integer count = 0;

public getCount()
{
   synchronized(count){
   return count;
   }
}

public void setCount(Integer i)
{
     synchronized(count){
         count = i;
       }
   }
}

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

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Оба ваших решения работают, однако в способе реализации блокировки есть ошибка.

Сначала разница в двух подходах: ReentrantReadWriteLock в основном используется в ситуациях, когда у вас гораздо больше операций чтения, чем операций записи, как правило, в соотношении 10 операций чтения: 1 запись. Это позволяет выполнять чтение одновременно, не блокируя друг друга, однако, когда начинается запись, все чтения будут заблокированы. Таким образом, производительность является основной причиной.

Ошибка в вашем подходе: Объект, к которому вы привязываетесь, должен быть окончательным. В setCount () вы эффективно меняете объект, что может привести к неправильному чтению в это время.

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

1 голос
/ 02 апреля 2019

ReentrantReadWriteLock - лучший способ реализовать ваши мысли.Синхронизировал бы только один поток, если два или более потоков пытаются прочитать счетчик.Но каждый может получить значение count, когда все попытаются его прочитать.

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