阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用ReadWriteLock

64次阅读
没有评论

共计 1295 个字符,预计需要花费 4 分钟才能阅读完成。

前面讲到的 ReentrantLock 保证了只有一个线程可以执行临界区代码:

public class Counter {private final Lock lock = new ReentrantLock();
    private int[] counts = new int[10];

    public void inc(int index) {lock.lock();
        try {counts[index] += 1;
        } finally {lock.unlock();
        }
    }

    public int[] get() {lock.lock();
        try {return Arrays.copyOf(counts, counts.length);
        } finally {lock.unlock();
        }
    }
}

但是有些时候,这种保护有点过头。因为我们发现,任何时刻,只允许一个线程修改,也就是调用 inc() 方法是必须获取锁,但是,get()方法只读取数据,不修改数据,它实际上允许多个线程同时调用。

实际上我们想要的是:允许多个线程同时读,但只要有一个线程在写,其他线程就必须等待:

允许 不允许
不允许 不允许

使用 ReadWriteLock 可以解决这个问题,它保证:

  • 只允许一个线程写入(其他线程既不能写入也不能读取);
  • 没有写入时,多个线程允许同时读(提高性能)。

ReadWriteLock 实现这个功能十分容易。我们需要创建一个 ReadWriteLock 实例,然后分别获取读锁和写锁:

public class Counter {private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
    // 注意: 一对读锁和写锁必须从同一个 rwlock 获取:
    private final Lock rlock = rwlock.readLock();
    private final Lock wlock = rwlock.writeLock();
    private int[] counts = new int[10];

    public void inc(int index) {wlock.lock(); // 加写锁
        try {counts[index] += 1;
        } finally {wlock.unlock(); // 释放写锁
        }
    }

    public int[] get() {rlock.lock(); // 加读锁
        try {return Arrays.copyOf(counts, counts.length);
        } finally {rlock.unlock(); // 释放读锁
        }
    }
}

把读写操作分别用读锁和写锁来加锁,在读取时,多个线程可以同时获得读锁,这样就大大提高了并发读的执行效率。

使用 ReadWriteLock 时,适用条件是同一个数据,有大量线程读取,但仅有少数线程修改。

例如,一个论坛的帖子,回复可以看做写入操作,它是不频繁的,但是,浏览可以看做读取操作,是非常频繁的,这种情况就可以使用ReadWriteLock

小结

使用 ReadWriteLock 可以提高读取效率:

  • ReadWriteLock只允许一个线程写入;
  • ReadWriteLock允许多个线程在没有写入时同时读取;
  • ReadWriteLock适合读多写少的场景。

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计1295字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中