ReentrantReadWriteLock:读锁和写锁有什么区别?

58

我所知道的是:

  • ReadLockWriteLock 彼此会产生影响
  • WriteLock 就像是 synchronized
  • ReadLock 似乎不能单独使用
5个回答

155

readLock.lock();

  • 这意味着如果任何其他线程正在写入(即持有写锁),则在此处停止,直到没有其他线程正在写入为止。
  • 一旦授予了锁定,其他线程将被禁止写入(即获取写锁),直到释放该锁。

writeLock.lock();

  • 这意味着如果任何其他线程正在读取或写入,请在此处停止并等待,直到没有其他线程正在读取或写入。
  • 一旦授予了锁定,其他线程将被禁止读取或写入(即获取读取或写入锁),直到释放该锁。

通过组合上述操作,您可以安排仅有一个线程同时具有写访问权限,但是您可以让多个读取者同时读取,除非正在写入线程。

换句话说,每次要从结构中读取时,请使用读取锁定。每次要写入时,请使用写入锁定。这样,每当进行写入时,没有人在读取(您可以想象您拥有独占访问权限),但是只要没有人在写入,就可以有多个读取者同时读取。


7
好的解释。仅供说明,通过“one”,您的意思是“线程”。 - Eng.Fouad

22

ReadWriteLock文档中已经明确说明:

一个ReadWriteLock维护一对相关的锁,一个用于只读操作,另一个用于写操作。 只要没有写入者,读取锁可以被多个读取线程同时持有。写锁是独占的。

因此,您可以同时拥有多个读取器,但只能有一个写入器 - 而且写入器也会阻止读取器进行读取。 如果您拥有一些资源可以安全地从多个线程读取,而且读取比写入更常见,则此功能非常有用,但当此资源实际上不是只读时。 (如果没有写入者并且读取是安全的,则根本不需要锁定。)


1
如果有100个读者,其中1个写者想要获取锁,那么读者会被中断吗?还是写者必须等到当前的读者释放锁? - Vipin
1
@Vipin:作者必须等待。 - Jon Skeet
现在你的答案完美无缺 :) - Vipin
例如,读者A正在阅读。然后写作者B来了,所以写作者B会等待。当B在等待时,读者C出现了。因此,读者C将等待B运行并完成,或者读者C可以尽快阅读。谢谢。 - hqt
@hqt读取器C将开始读取,B将等待其完成。只有在B已经开始写入时,C才会等待。 - Carlos Melo
如果您不编写ReadLock->它将升级读取器并导致死锁(允许读线程升级将导致死锁,因为多个线程可以尝试升级其锁)。 - Musa

10

当一个线程获取WriteLock时,其他线程无法获取同一实例的ReentrantReadWriteLockReadLockWriteLock,除非该线程释放锁。但是,多个线程可以同时获取ReadLock


2
使用ReadWriteLock,您可以提高应用程序的性能,特别是在共享对象上执行更多读操作而不是写操作的情况下。
ReadWriteLock维护了两个锁,一个用于读操作,另一个用于写操作。同一时间只能获取一个锁,无论是读锁还是写锁。但是,如果没有任何线程获取写锁,则多个线程可以同时获取读锁。
ReentrantReadWriteLock是ReadWriteLock的实现。如果有多个线程等待读锁,则它会将写锁授予最长等待的线程。如果有多个线程等待读锁,则它会将读锁授予它们。
已获得读锁的读取器可以重新获取读锁,类似地,编写器可以重新获取写锁,并且也可以获取读锁。
请参见http://www.zoftino.com/java-concurrency-lock-and-condition-examples

提醒一下,zoftino的链接已经失效。 - Paul Gregoire

0
考虑这样一种情况:在数据结构“读多写少”的情况下,它们是可变的,有时会被修改,但大多数访问都涉及到读取,因此在这些情况下,我们可以放松锁定机制,允许多个读者访问数据结构,而不是等待一个读者释放锁。只要每个线程都保证了共享数据的最新视图,并且在读者查看数据时没有线程对其进行修改,就不会出现问题。这就是读写所允许的:资源可以同时被多个读者或单个写者访问,但不能同时进行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接