Правильное использование блокировок чтения-записи

У меня есть требование, как показано ниже:

1) Класс, который имеет все статические методы и статический список. В этом списке хранятся некоторые объекты, над которыми я выполняю некоторые операции.

2) Теперь эта операция вызывается из нескольких потоков.

3) этот вызов операции не разделяет какие-либо общие данные, поэтому эти методы не синхронизированы.

4) теперь, когда этот список обновляется новыми объектами, я должен прекратить этот вызов операции.

class StaticClass{
    static List<SomeObjects>=new List<>();
    static performOperation()
    {
        //call operation on all objects in the list
    }

    static updateList()
    {
        //update list, add, update or remove objects 
    }
}

Возможные решения:

1) Выполните синхронизацию executeOperation() и updateList(). Но частота, с которой вызывается метод executeOperation(), слишком высока, а частота списка обновлений слишком низкая.

2) использовать блокировки чтения-записи. Используйте блокировки чтения в executeOperation() и блокировки записи в updateList(). Пример показан ниже:

class StaticClass{
    static List<SomeObjects>=new List<>();
    static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    static performOperation()
    {
        readWriteLock.readLock().lock();
        //call operation on all objects in the list
        readWriteLock.readLock().unlock();
    }

    static updateList()
    {
        readWriteLock.writeLock().lock();
        //update list, add, update or remove objects 
        readWriteLock.writeLock().unlock();
    }

Так какое решение лучше? Это правильное использование блокировок readwrite. Почему я путаюсь с подходом 2, так это то, что в executeOperation() нет таких данных, которые требуют доступа для чтения или записи. Я просто не могу вызвать этот метод, когда список обновляется. Так что я не уверен, является ли это правильным использование блокировки чтения-записи или нет.

1 ответ

ReadWriteLock является более эффективным, когда много чтения происходит как synchronized заблокирует все Что сказал ReadWriteLock более подвержен ошибкам. Например, ваш пример на самом деле окажется в тупике, потому что каждый раз, когда вы вызываете readWriteLock.writeLock() или же readWriteLock.readLock() он создаст новый экземпляр и никогда не будет разблокирован, в результате чего он окажется в мертвой блокировке. Итак, ваш пример должен выглядеть так:

class StaticClass{
    static List<SomeObjects>=new List<>();
    static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    static final Lock readLock = readWriteLock.readLock();
    static final Lock writeLock = readWriteLock.writeLock();

    static void performOperation()
    {
        readLock.lock();
        try {
            //call operation on all objects in the list
        } finally {
            // This ensures read lock is unlocked even when exception occurs
            readLock.unlock();
        }
    }

    static void updateList()
    {
        writeLock.lock();
        try {
            //update list, add, update or remove objects 
        } finally {
            // This ensures read lock is unlocked even when exception occurs
            writeLock.unlock();
        }
    }
}

Обратите внимание, я также добавил try/finally здесь, чтобы избежать возможных проблем с исключениями. Как вы видите, это гораздо больше работы, чем простой synchronized часть.

Также есть возможная альтернатива CopyOnWriteArrayList. Что потокобезопасно, и вам не нужно использовать блокировки или synchronized ключевое слово. Это повлияет на вашу производительность, когда в нее будет много записей.

Другие вопросы по тегам