正确使用读写锁

时间:2018-07-10 13:19:08

标签: java multithreading locking readwritelock

我的要求如下:

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()的调用频率太高,udpate列表频率太低。

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()中没有需要读取或写入访问的数据。当列表正在更新时,我只是无法调用此方法。因此,我不确定它是否适合使用读写锁。

1 个答案:

答案 0 :(得分: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关键字。写入大量内容时,它将影响您的性能。