读写锁

读写锁是什么?

读写锁(Read-Write Lock)是一种同步机制,用于解决多线程环境下的资源访问问题。它允许多个线程同时读取共享资源,但在写入资源时,只有一个线程可以进行写操作,并且在写操作进行期间,不允许其他线程读取该资源。读写锁的设计目的是提高系统在多线程环境下的并发性,同时确保数据的一致性。

读写锁的两种状态

读锁(共享锁,Read Lock): 多个线程可以同时获得读锁,只要没有任何线程持有写锁。 读锁的特点是共享的,多个读线程可以并发地读取数据,而不会相互阻塞。
写锁(排它锁,Write Lock): 写锁是独占的,意味着一旦一个线程获得写锁,其他线程(无论是读线程还是写线程)都将被阻塞,直到该线程释放写锁。 在写操作进行时,系统不允许任何读操作,以防止读取到不一致的数据。

工作机制

当一个线程尝试获取读锁时,读写锁会检查当前是否有其他线程持有写锁。如果没有写锁,则该线程可以获得读锁并读取资源。 如果一个线程尝试获取写锁,读写锁会阻塞该线程,直到所有持有读锁的线程释放读锁,并且没有其他线程持有读锁或写锁。 一旦写锁被获取,其他请求读锁和写锁的线程都将被阻塞,直到写锁被释放。

优缺点

读写锁的优点:
-提高并发性:在读操作频繁且写操作较少的情况下,读写锁可以显著提高系统的并发性能。
-数据一致性:通过独占写锁,可以确保写操作对资源的一致性和完整性。

读写锁的缺点:
-复杂性增加:相比于普通的互斥锁(如Mutex),读写锁的实现和使用更加复杂。
-可能导致写饥饿:如果读操作非常频繁,写线程可能会长时间得不到写锁,从而导致“写饥饿”问题。

应用场景

读写锁在需要高并发读取而较少写入的场景中非常有用,如缓存、配置读取等系统中。

示例

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
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock(); //读锁
private static Lock writeLock = readWriteLock.writeLock(); //写锁

private int value; //需要修改的数据

public int read() throws InterruptedException {
try {
readLock.lock(); // 获取读锁
Thread.sleep(1); // 模拟读取操作的延迟
return value; // 返回当前的value值
} finally {
readLock.unlock(); // 确保在读取完成后释放读锁
}
}

public void Write(int index) throws InterruptedException {
try {
writeLock.lock(); // 获取写锁
Thread.sleep(1); // 模拟写入操作的延迟
value = index; // 更新value的值
} finally {
writeLock.unlock(); // 确保在写入完成后释放写锁
}
}
总结:创建锁->上锁->释放锁