首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java并发-读写锁性能

Java并发-读写锁性能
EN

Stack Overflow用户
提问于 2021-04-22 19:53:26
回答 2查看 339关注 0票数 2

我在试着理解ReadWriteLock。这段代码将只在IDE中工作。复制和粘贴。试着自己去做

代码语言:javascript
复制
class ReadWrite {

    private static final ReadWriteLock LOCK = new ReentrantReadWriteLock();
    private static final Lock READ_LOCK = LOCK.readLock();
    private static final Lock WRITE_LOCK = LOCK.writeLock();
    private static final int[] ARR = new int[1];
    int i = 0;

    Integer read(){
        Integer value = null;
        try{
            READ_LOCK.lock();
            value = ARR[0];
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            READ_LOCK.unlock();
        }
        return value;
    }


    void write(){
        try{
            WRITE_LOCK.lock();
            ARR[0] = i++;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            WRITE_LOCK.unlock();
        }
    }

}

我正试着做一个性能测试。

代码语言:javascript
复制
        AtomicInteger atomicInteger = new AtomicInteger(0);
        ReadWrite rw = new ReadWrite();
        // read 10 millions times
    Runnable r1 = () -> IntStream.rangeClosed(1, 10_000_000).forEach(i -> {
        if(rw.read() > 0)
            atomicInteger.incrementAndGet();
    });
        Runnable r2 = rw::write;

        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        Thread[] threads = new Thread[10];

        long before = System.currentTimeMillis();
        scheduledExecutorService.scheduleAtFixedRate(r2, 1, 1, TimeUnit.MICROSECONDS);
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(r1);
            threads[i].start();
        }
        for (int i = 0; i < 10; i++) {
            threads[i].join();
        }
        System.out.println("Time Taken :: " + (System.currentTimeMillis() - before));
       System.out.println("No fo reads :: " + atomicInteger.get());

做了几次测试。

案例1:

当我使用READ_LOCK阅读时,它需要12秒才能完成。没有读取是100000000

案例2:

当我同时使用WRITE_LOCK进行读写(本例中没有使用READ_LOCK)时,测试只需2.5秒。没有读取是100000000

我在想,使用单独的锁可以提高性能。

这里发生什么事情?我犯了什么错?

EN

回答 2

Stack Overflow用户

发布于 2021-04-22 20:18:57

您正在运行read() 1000万次(* 10个线程)。只运行一次write()。写入所用时间为2.5秒,因为只有在没有带有读锁的线程时,它才能接受写锁。

此外,正如@Burak提到的,您没有在这里测量正确的东西。

您应该使用读锁运行同一方法一次,用写锁运行一次。例如,使用10个线程运行此方法。例如,该方法将迭代1到1000万次。

此外,您正在计算在测试中创建线程的时间(这不是锁机制的一部分)。您应该在前面创建线程)

然后,您将看到写锁方法比读锁慢。为什么?因为当线程接受写锁时,只有这个线程才能执行方法代码。在读取锁的情况下,所有10个线程都将并行运行该方法。

票数 1
EN

Stack Overflow用户

发布于 2021-04-23 08:59:45

ReadWriteLock的文档提到了以下内容:

此外,如果读操作太短,读写锁实现的开销(本质上比互斥锁更复杂)可以控制执行成本,特别是因为许多读写锁实现仍然通过一小部分代码序列化所有线程。最终,只有分析和测量才能确定读写锁的使用是否适合您的应用程序。

您的读取确实非常快,因此您正在观察读写锁在简单锁上的开销。

读写锁的实现涉及什么?首先,实际上有两个锁。读取锁可以由多个线程获取,这使得它不同于简单的可重入锁,并且它必须检查写锁在试图锁定时是否已锁定。在试图锁定时,写入器锁必须检查没有锁定的读取器,但它与单线程可重入锁类似。

对于细粒度的访问,例如在您的示例中,读写锁是不值得的。当访问一组数据(如“页面”数据)(例如数百或数千个缓存的数据库行)时,开销可能可以忽略不计。

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

https://stackoverflow.com/questions/67219909

复制
相关文章

相似问题

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