当前位置:   article > 正文

Java并发编程 - 读写锁ReadWriteLock详解

Java并发编程 - 读写锁ReadWriteLock详解

在Java并发编程中,读写锁(ReadWriteLock)是一种非常有用的同步机制,它允许多个读取者同时访问共享资源,但在任何时候只允许一个写入者访问。这可以显著提高并发性能,特别是在读取操作远多于写入操作的情况下。

ReadWriteLock接口

ReadWriteLock是一个接口,定义了读锁和写锁的行为。它有两个方法,分别返回读锁和写锁:

  • Lock readLock():返回读锁。
  • Lock writeLock():返回写锁。

ReentrantReadWriteLock

ReentrantReadWriteLockReadWriteLock的一个实现,它允许重入,即一个线程可以多次获取同一个锁。

特点
  • 读锁:多个线程可以同时持有读锁,只要没有线程持有写锁。
  • 写锁:一次只能有一个线程持有写锁,持有写锁时不允许其他线程获取读锁或写锁。
使用场景
  • 当读取操作远多于写入操作时,使用读写锁可以显著提高并发性能。
  • 写入操作通常需要独占访问共享资源,以防数据不一致。
  • 读取操作通常不需要修改资源,因此可以允许多个线程同时读取。

示例代码

下面是一个简单的示例,演示如何使用ReentrantReadWriteLock

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockExample {

    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private int count = 0;

    public void readValue() {
        readLock.lock();
        try {
            System.out.println("Reading: " + count);
        } finally {
            readLock.unlock();
        }
    }

    public void writeValue(int value) {
        writeLock.lock();
        try {
            count = value;
            System.out.println("Writing: " + count);
        } finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        ReadWriteLockExample example = new ReadWriteLockExample();

        Thread reader1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                example.readValue();
            }
        });

        Thread reader2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                example.readValue();
            }
        });

        Thread writer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                example.writeValue(i * 10);
            }
        });

        reader1.start();
        reader2.start();
        writer.start();

        try {
            reader1.join();
            reader2.join();
            writer.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

在这个示例中,我们创建了一个ReentrantReadWriteLock实例,并从中获取了读锁和写锁。readValue方法用于读取count变量,而writeValue方法用于写入新的值。多个读线程可以同时访问count,但写线程会独占访问。

读写锁的特点

  1. 重入性:线程可以多次获取同一类型的锁。
  2. 公平性:可以选择创建公平锁或非公平锁。公平锁保证按请求顺序获取锁,非公平锁则可能允许后来的线程抢先获取锁。
  3. 升级和降级:线程可以先获取读锁,然后再获取写锁(升级),或者先获取写锁,然后再获取读锁(降级)。

升级和降级

在某些情况下,可能需要先获取读锁,然后在需要写入数据时再升级为写锁。同样,也可能需要先获取写锁,然后在读取数据时降级为读锁。ReentrantReadWriteLock支持升级和降级,但需要显式地管理。

示例代码

下面是一个升级和降级的示例:

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class UpgradeDowngradeExample {

    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private int count = 0;

    public void updateValue(int value) {
        readLock.lock();
        try {
            System.out.println("Reading: " + count);
            if (value > count) {
                writeLock.lock();
                try {
                    System.out.println("Upgrading to write lock.");
                    count = value;
                    System.out.println("Writing: " + count);
                } finally {
                    writeLock.unlock();
                }
            }
        } finally {
            readLock.unlock();
        }
    }

    public static void main(String[] args) {
        UpgradeDowngradeExample example = new UpgradeDowngradeExample();

        Thread updater = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                example.updateValue(i * 10);
            }
        });

        updater.start();

        try {
            updater.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

在这个示例中,updateValue方法首先获取读锁来检查当前值,如果需要更新,则进一步获取写锁以执行写入操作。这展示了如何从读锁升级到写锁的过程。

总结

读写锁是一种非常有效的同步机制,尤其适用于读取操作远多于写入操作的场景。通过允许多个读取者同时访问共享资源,可以显著提高并发性能。ReentrantReadWriteLock提供了丰富的功能,包括升级和降级锁的能力,使得它成为一个强大且灵活的工具。在实际应用中,合理选择锁的类型和管理锁的使用可以大大提高程序的性能和可维护性。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/995424
推荐阅读
相关标签
  

闽ICP备14008679号