我想知道ReentrantLock和ReentrantReadWriteLock在逻辑上有什么不同。换句话说,是否存在只需要一个没有读/写锁的锁的情况,反之亦然,读/写锁和只有一个锁是不够的?
考虑以下仅使用锁的主要示例:
public class Counter {
private int counter = 0;
private ReentrantLock lock = new ReentrantLock(true);
public void increment() {
lock.lock();
counter += 1;
lock.unlock();
}
public int getCounter() {
return counter;
}
}考虑下面的读写锁示例,并将其与前面的示例进行比较:
public class Counter {
private int counter = 0;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
public void increment() {
lock.writeLock().lock();
try {
counter += 1;
} finally {
lock.writeLock().unlock();
}
}
public int getCounter() {
lock.readLock().lock();
try {
return counter;
} finally {
lock.readLock().unlock();
}
}
}就线程安全性而言,这两个选项中哪一个是正确的实现?为什么?
发布于 2019-09-06 00:19:03
使用ReentrantLock或ReentrantReadWriteLock取决于您想要解决的用例。
在您的第一个示例中,getCounter()方法没有锁。因此,当线程在增量方法中保存ReentrantLock时,获取计数器是可能的。
在您的第二个示例中,当线程在增量方法中持有writeLock()时,您无法获取计数器。并且保持readLock()可以防止计数器递增。读取你的counter参数的几个线程可能同时持有readLock()。
发布于 2019-09-08 11:18:36
当读操作多于写操作时,通过仔细控制AbstractQueuedSynchronizer$state,ReentrantReadWriteLock可以提供更高的性能。
如果不是,则控制开销比ReentrantLock更高。
对于您的第一个示例,您不需要考虑getCounter()方法的原子性问题是正确的,但是应该考虑可见性问题。即使其他线程已经递增了计数器,一个线程也可以看到初始值。
https://stackoverflow.com/questions/57809112
复制相似问题