Java
读写锁(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();