读写锁。了解从 readLock 升级到 writeLock
ReadWriteLock. Understanding upgrading from readLock to writeLock
考虑这个 JDK
标准接口:
public interface ReadWriteLock{
public Lock readLock();
public Lock writeLock();
}
乙。 Goetz 在 Java 并发实践中提到从 readLock 升级到 writeLock 容易死锁。
If two readers simultaneously attempt to upgrade to a write lock,
neither will realese the read lock.
让我感到困惑的是 两个 reader 试图升级。但即使一个 reader 就足够了,不是吗?如果 reader 尝试升级它还没有释放读锁。试图在持有读锁的情况下获取写锁是死锁。
所以从这一点来看,我认为提供升级操作在理论上是荒谬的。或者也许一个实现可以解决这个问题?
听起来您正在考虑 "read lock" 和 "write lock" 是两个不同的锁,它们组成一个读写锁。这不是正确的思考方式,即使 API 似乎公开了这样的组合(通过提供方法来获取对 "write lock" 和 "read lock" 的引用)。
(由于术语 "lock" 的重载,这一切都有些混乱 - 它既是 动词 又是 名词 , 即可以 lock a lock).
与其认为 ReadWriteLock
的 readLock
方法和 writeLock
方法 return 实际锁定,不如考虑它们实际做的是 return abstract mechanism 允许获取不同类型的锁(在 same,单一,读写锁机制上)。
读写锁(机制)是一个单锁,可以通过两种方式锁定:读锁和写锁定。读写锁可以被一个或多个线程并发读锁,也可以写锁。它永远不能同时被读和写锁定。
If a reader tries to upgrade it's not released the read lock yet. Trying to acquire the write lock with the read lock held is deadlocky.
写锁比读锁强;它就像一个带有附加 属性 的读锁(没有其他线程也可以持有该锁)。从读锁升级到写锁并不是在已经持有另一个锁的情况下获取一个锁;相反,它是关于更改已经在单个锁上的锁的类型。
因此,单线程将读锁升级为写锁在概念上没有问题;它只需要等到读锁的所有其他持有者在升级发生之前放弃它。这种情况下不存在死锁的可能。
例如,假设有三个线程——A、B和C,它们都读锁了锁。线程 A 尝试升级到写锁。这意味着它必须等待 B 和 C 放弃它们的读锁。这最终会发生,此时线程 A 获得一个写锁(并且,最终,线程 A 将放弃这个锁)。
另一方面考虑A和B是否都尝试升级写锁。这意味着他们都在等待对方放弃读锁,这不会发生;对于线程 A 放弃读锁,它首先需要获取写锁,直到线程 B 放弃读锁,它才会这样做,直到它获得写锁,这不会发生直到线程 A 放弃读锁……等等。出现死锁。
Java API 不允许从读锁升级到写锁,因为这可以防止死锁情况。编写一个可以安全升级锁类型的程序是可能的(如果有点棘手的话),但是 Java API 无论如何都不允许这样做。
考虑这个 JDK
标准接口:
public interface ReadWriteLock{
public Lock readLock();
public Lock writeLock();
}
乙。 Goetz 在 Java 并发实践中提到从 readLock 升级到 writeLock 容易死锁。
If two readers simultaneously attempt to upgrade to a write lock, neither will realese the read lock.
让我感到困惑的是 两个 reader 试图升级。但即使一个 reader 就足够了,不是吗?如果 reader 尝试升级它还没有释放读锁。试图在持有读锁的情况下获取写锁是死锁。
所以从这一点来看,我认为提供升级操作在理论上是荒谬的。或者也许一个实现可以解决这个问题?
听起来您正在考虑 "read lock" 和 "write lock" 是两个不同的锁,它们组成一个读写锁。这不是正确的思考方式,即使 API 似乎公开了这样的组合(通过提供方法来获取对 "write lock" 和 "read lock" 的引用)。
(由于术语 "lock" 的重载,这一切都有些混乱 - 它既是 动词 又是 名词 , 即可以 lock a lock).
与其认为 ReadWriteLock
的 readLock
方法和 writeLock
方法 return 实际锁定,不如考虑它们实际做的是 return abstract mechanism 允许获取不同类型的锁(在 same,单一,读写锁机制上)。
读写锁(机制)是一个单锁,可以通过两种方式锁定:读锁和写锁定。读写锁可以被一个或多个线程并发读锁,也可以写锁。它永远不能同时被读和写锁定。
If a reader tries to upgrade it's not released the read lock yet. Trying to acquire the write lock with the read lock held is deadlocky.
写锁比读锁强;它就像一个带有附加 属性 的读锁(没有其他线程也可以持有该锁)。从读锁升级到写锁并不是在已经持有另一个锁的情况下获取一个锁;相反,它是关于更改已经在单个锁上的锁的类型。
因此,单线程将读锁升级为写锁在概念上没有问题;它只需要等到读锁的所有其他持有者在升级发生之前放弃它。这种情况下不存在死锁的可能。
例如,假设有三个线程——A、B和C,它们都读锁了锁。线程 A 尝试升级到写锁。这意味着它必须等待 B 和 C 放弃它们的读锁。这最终会发生,此时线程 A 获得一个写锁(并且,最终,线程 A 将放弃这个锁)。
另一方面考虑A和B是否都尝试升级写锁。这意味着他们都在等待对方放弃读锁,这不会发生;对于线程 A 放弃读锁,它首先需要获取写锁,直到线程 B 放弃读锁,它才会这样做,直到它获得写锁,这不会发生直到线程 A 放弃读锁……等等。出现死锁。
Java API 不允许从读锁升级到写锁,因为这可以防止死锁情况。编写一个可以安全升级锁类型的程序是可能的(如果有点棘手的话),但是 Java API 无论如何都不允许这样做。