首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读写锁的正确用法

读写锁的正确用法
EN

Stack Overflow用户
提问于 2018-07-10 21:19:08
回答 1查看 49关注 0票数 0

我有一个要求,如下:

1)包含所有静态方法和静态列表的类。这个列表存储了一些对象,我对这些对象执行了一些操作。

2)现在这个操作被多个线程调用了。

3)此操作调用没有共享任何公共数据,因此此方法不同步。

4)现在,每当这个列表使用新对象更新时,我必须停止这个操作调用。

代码语言:javascript
复制
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()中使用写锁。示例如下:

代码语言:javascript
复制
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()中没有需要读访问或写访问的数据。当list被更新时,我不能调用这个方法。所以我不确定这是否是读写锁的恰当使用。

EN

回答 1

Stack Overflow用户

发布于 2018-07-10 21:42:17

当发生大量读取时,ReadWriteLock会更有效,因为synchronized会阻塞所有内容。也就是说,ReadWriteLock更容易出错。例如,您的示例实际上将以死锁告终,因为每次您调用readWriteLock.writeLock()readWriteLock.readLock()时,它都会创建一个新实例,并且永远不会解锁,从而导致它以死锁告终。所以你的例子应该看起来更像:

代码语言:javascript
复制
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关键字。当有大量的写操作时,它会影响你的性能。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51266361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档