3 java multithreading readwritelock
考虑以下JDK
标准接口:
public interface ReadWriteLock{
public Lock readLock();
public Lock writeLock();
}
Run Code Online (Sandbox Code Playgroud)
B. Goetz在Java Concurrency中实际上提到从readLock升级到writeLock容易死锁。
如果两个读取器同时尝试升级到写入锁,则任何一个都不会重新获得读取锁。
让我感到困惑的是,有两个读者试图升级。但是,即使一个读者也足够了,不是吗?如果读取器尝试升级,则不会释放读取锁。试图在持有读锁定的情况下获取写锁定是死锁的。
因此,从这一点来看,我认为提供升级操作在理论上甚至都是荒谬的。也许实现可以解决这个问题?
听起来您正在考虑将“读锁”和“写锁”视为组成读写锁的两个不同的锁。即使API似乎公开了这种组合(通过提供获取对“写锁”和“读锁”的引用的方法),这也不是正确的思考方式。
(这是全部由术语“锁”的超载困惑一点-它既是一个动词和名词,也就是一个可以锁定一个锁)。
与其认为ReadWriteLock
的readLock
方法和writeLock
方法返回了实际的锁,不如考虑它们的实际操作是返回一种抽象机制,该机制允许获取不同类型的锁(在同一,单个,读写锁机制上)。
读写锁(机制)是单个锁,可以通过两种方式锁定:读锁定和写锁定。读写锁可以同时被一个或多个线程读锁,也可以被写锁。永远不能同时对其进行读取和写入锁定。
如果读取器尝试升级,则不会释放读取锁。试图在持有读锁定的情况下获取写锁定是死锁的。
写锁比读锁强。就像具有附加属性的读锁(没有其他线程也可以持有该锁)一样。从读锁升级到写锁并不是要在已经持有另一个锁的情况下获得一个锁。而是要更改已保存在单个锁上的锁的类型。
因此,单线程将其读取锁升级为写入锁没有任何概念上的问题。它只需要等到读锁的所有其他持有者都将其放弃才能进行升级。在这种情况下,没有死锁的可能性。
例如,假设有三个线程-A,B和C,它们都已读锁定该锁。线程A尝试升级到写锁。这意味着它必须等待B和C放弃读取锁。最终发生这种情况,此时线程A获得了一个写锁(最终,线程A随后将放弃此锁)。
另一方面,请考虑A和B是否都尝试升级到写锁。这意味着他们都在等待对方放弃读锁,这不会发生。为了使线程A放弃读锁定,它首先需要获取写锁定,直到线程B放弃读锁定,该锁定才会发生,直到线程B放弃获得写锁定的该锁定才发生。直到线程A放弃读取锁...等等。陷入僵局。
Java API不允许从读锁升级到写锁,因为这样可以防止出现死锁情况。可能(如果有些棘手)编写可以安全升级锁类型的程序,但是Java API不允许这样做。
归档时间: |
|
查看次数: |
803 次 |
最近记录: |