考虑一下这个JDK标准接口:
public interface ReadWriteLock{
public Lock readLock();
public Lock writeLock();
}B. Goetz在Java中的并发性实际上提到了从readLock升级到writeLock是很容易死锁的。
如果两个读取器同时尝试升级到写锁,则两者都不会实现读锁。
让我感到困惑的是,是两个阅读器试图升级。但即使是一个读者也足够了,不是吗?如果读取器试图升级,它还没有释放读锁。试图用所持有的读锁获取写锁是死锁。
因此,从这一点来看,我认为提供升级操作在理论上甚至是荒谬的。或者一个实现可以解决这个问题?
发布于 2016-05-07 10:17:36
听起来你认为“读锁”和“写锁”是两种不同的锁,它们构成读写锁。这不是正确的思考方法,即使API似乎公开了这样一个组合(通过提供方法获得对“写锁”和“读锁”的引用)。
(“锁”一词的过载使这一切有点混乱-它既是动词又是名词,也就是可以锁定锁)。
与其认为ReadWriteLock的readLock方法和writeLock方法返回实际锁,不如考虑它们实际上是返回一种抽象机制,允许获取不同类型的锁(在相同的、单一的读写锁机制上)。
读-写锁(机制)是一个单一的锁,可以通过两种方式锁定:读锁和写锁。读写锁可以由一个或多个线程同时读锁,也可以写锁.它永远不可能同时被读-写-锁。
如果读取器试图升级,它还没有释放读锁。试图用所持有的读锁获取写锁是死锁。
写锁比读锁强;它就像具有附加属性的读锁(其他线程也不能持有该锁)。从读锁升级到写锁并不是在另一个锁已经持有时获取一个锁,而是要更改已在单个锁上持有的锁的类型。
因此,单个线程将其读锁升级为写锁没有概念上的问题;它只需要等待读锁的所有其他持有者在升级之前放弃它。在这种情况下不可能陷入僵局。
例如,假设有三个线程- A、B和C,所有这些线程都已锁定锁。线程A试图升级到写锁.这意味着它必须等待B和C放弃它们的读锁。这最终会发生,此时线程A将获得一个写锁(最终,线程A将放弃此锁)。
另一方面,考虑一下A和B是否都试图升级到写锁。这意味着它们都在等待另一个放弃读锁,这是不会发生的;线程A要放弃读锁,首先需要获得写锁,这种情况在线程B放弃读锁之前不会发生,直到线程A放弃读锁时才会发生。诸若此类。出现了僵局。
Java不允许从读锁升级到写锁,因为这样可以防止死锁的发生。编写一个可以安全升级锁类型的程序是可能的(如果有点棘手的话),但是Java无论如何都不允许它。
https://stackoverflow.com/questions/37087120
复制相似问题