0

我有一个要求如下:

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) 使 performOperation() 和 updateList() 同步。但是 performOperation() 被调用的频率太高,而更新列表频率太低。

2)使用读写锁。在 performOperation() 中使用读锁,在 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();
    }

那么哪种解决方案更好呢?这是读写锁的正确用法吗?为什么我对方法 2 感到困惑是 performOperation() 中没有需要读访问或写访问的数据。我只是在更新列表时无法调用此方法。所以我不确定它是否适合使用读写锁。

4

1 回答 1

0

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关键字。当有大量写入时,它会影响您的性能。

于 2018-07-10T13:42:17.413 回答