关于java:面试突击45为什么要用读写锁它有什么优点

7次阅读

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

读写锁(Readers-Writer Lock)顾名思义是一把锁分为两局部:读锁和写锁,其中读锁容许多个线程同时取得,因为读操作自身是线程平安的,而写锁则是互斥锁,不容许多个线程同时取得写锁,并且写操作和读操作也是互斥的。总结来说,读写锁的特点是: 读读不互斥、读写互斥、写写互斥

1. 读写锁应用

在 Java 语言中,读写锁是应用 ReentrantReadWriteLock 类来实现的,其中:

  • ReentrantReadWriteLock.ReadLock 示意读锁,它提供了 lock 办法进行加锁、unlock 办法进行解锁。
  • ReentrantReadWriteLock.WriteLock 示意写锁,它提供了 lock 办法进行加锁、unlock 办法进行解锁。

它的根底应用如下代码所示:

// 创立读写锁
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 取得读锁
final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
// 取得写锁
final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
// 读锁应用
readLock.lock();
try {// 业务代码...} finally {readLock.unlock();
}
// 写锁应用
writeLock.lock();
try {// 业务代码...} finally {writeLock.unlock();
}

1.1 读读不互斥

多个线程能够同时获取到读锁,称之为读读不互斥,如下代码所示:

// 创立读写锁
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 创立读锁
final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
Thread t1 = new Thread(() -> {readLock.lock();
    try {System.out.println("[t1] 失去读锁.");
        Thread.sleep(3000);
    } catch (InterruptedException e) {e.printStackTrace();
    } finally {System.out.println("[t1] 开释读锁.");
        readLock.unlock();}
});
t1.start();
Thread t2 = new Thread(() -> {readLock.lock();
    try {System.out.println("[t2] 失去读锁.");
        Thread.sleep(3000);
    } catch (InterruptedException e) {e.printStackTrace();
    } finally {System.out.println("[t2] 开释读锁.");
        readLock.unlock();}
});
t2.start();

以上程序执行后果如下:

1.2 读写互斥

读锁和写锁同时应用是互斥的(也就是不能同时取得),这称之为读写互斥,如下代码所示:

// 创立读写锁
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 创立读锁
final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
// 创立写锁
final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
// 应用读锁
Thread t1 = new Thread(() -> {readLock.lock();
    try {System.out.println("[t1] 失去读锁.");
        Thread.sleep(3000);
    } catch (InterruptedException e) {e.printStackTrace();
    } finally {System.out.println("[t1] 开释读锁.");
        readLock.unlock();}
});
t1.start();
// 应用写锁
Thread t2 = new Thread(() -> {writeLock.lock();
    try {System.out.println("[t2] 失去写锁.");
        Thread.sleep(3000);
    } catch (InterruptedException e) {e.printStackTrace();
    } finally {System.out.println("[t2] 开释写锁.");
        writeLock.unlock();}
});
t2.start();

以上程序执行后果如下:

1.3 写写互斥

多个线程同时应用写锁也是互斥的,这称之为写写互斥,如下代码所示:

// 创立读写锁
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 创立写锁
final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
Thread t1 = new Thread(() -> {writeLock.lock();
    try {System.out.println("[t1] 失去写锁.");
        Thread.sleep(3000);
    } catch (InterruptedException e) {e.printStackTrace();
    } finally {System.out.println("[t1] 开释写锁.");
        writeLock.unlock();}
});
t1.start();

Thread t2 = new Thread(() -> {writeLock.lock();
    try {System.out.println("[t2] 失去写锁.");
        Thread.sleep(3000);
    } catch (InterruptedException e) {e.printStackTrace();
    } finally {System.out.println("[t2] 开释写锁.");
        writeLock.unlock();}
});
t2.start();

以上程序执行后果如下:

2. 长处剖析

  1. 进步了程序执行性能:多个读锁能够同时执行,相比于一般锁在任何状况下都要排队执行来说,读写锁进步了程序的执行性能。
  2. 防止读到长期数据:读锁和写锁是互斥排队执行的,这样能够保障了读取操作不会读到写了一半的长期数据。

3. 实用场景

读写锁适宜多读少写的业务场景,此时读写锁的劣势最大。

总结

读写锁是一把锁分为两局部:读锁和写锁,其中读锁容许多个线程同时取得,而写锁则是互斥锁。它的残缺规定是:读读不互斥、读写互斥、写写互斥。它实用于多读的业务场景,应用它能够无效的进步程序的执行性能,也能防止读取到操作了一半的长期数据。

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java 面试真题解析

面试合集:https://gitee.com/mydb/interview

正文完
 0