java并发-读写锁性能

envsm3lx  于 2021-07-12  发布在  Java
关注(0)|答案(2)|浏览(416)

我正在努力理解readwritelock。[这段代码只能在ide中工作。复制和粘贴。你自己试试看]

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();
        }
    }

}

我想做一个性能测试。

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\u lock进行读取时,需要12秒才能完成。读取次数为100000000。
案例2:
当我对读写都使用write\u lock时(本例中不使用read\u lock),测试只需要2.5秒。读取次数为100000000。
我在想使用单独的锁应该可以提高性能。
这是怎么回事?我犯了什么错误?

sirbozc5

sirbozc51#

您正在运行read()1000万次(*10个线程)。只运行一次write()。。写操作花费了2.5秒,因为它只能在没有带读锁的线程的情况下获取写锁。
另外,正如@burak所提到的,你没有在这里测量正确的东西。
您应该使用read lock和write lock运行相同的方法一次。例如,用10个线程运行这个方法。例如,该方法将迭代100-1000万次。
此外,您正在计算在测试中创建线程的时间(这不是锁机制的一部分)。您应该在之前创建线程)
然后您将看到write lock方法比read lock慢。为什么?因为当一个线程获得写锁时,只有这个线程才能执行方法代码。在读锁的情况下,所有10个线程将并行运行该方法

rmbxnbpk

rmbxnbpk2#

readwritelock的文档提到:
此外,如果读操作太短,则读写锁实现的开销(其本质上比互斥锁更复杂)可以控制执行成本,特别是当许多读写锁实现仍然通过一小段代码序列化所有线程时。最终,只有评测和测量才能确定读写锁的使用是否适合您的应用程序。
您的读取速度确实非常快,因此您可以观察到读写锁相对于简单锁的开销。
读写锁的实现涉及到什么?首先,实际上有两个锁。读锁可能被多个线程占用,这使得它不同于简单的可重入锁,并且在尝试锁定时必须检查写锁是否未被锁定。writer锁在尝试锁定时必须检查是否没有锁定的读卡器,但它在其他方面类似于单线程可重入锁。
对于细粒度的访问,比如在您的示例中,读写锁是不值得的。当访问一组数据(例如一个“页面”的数据,例如数百或数千个缓存的数据库行)时,开销可能变得微不足道。

相关问题