第6章-ReadWriteLock

6.1 模式简介

  1. 学生们正在一起看老师在黑板上写的板书。这时,老师想擦掉板书,再写新的内容。而学生们说道:“老师,我们还没看完,请先不要擦掉!” 于是,老师就会等待大家都看完。
  2. 当线程 “读取” 实例的状态时,实例的状态不会发生变化。实例的状态仅在线程执行 “写入” 操作时才会发生变化。从实例的状态变化这个观点来看,“读取” 和 “写入” 有着本质的区别。
  3. 在Read-Write Lock模式中,读取操作和写入操作是分开考虑的。在执行读取操作之前,线程必须获取用于读取的锁。而在执行写入操作之前,线程必须获取用于写入的锁。
  4. 由于当线程执行读取操作时,实例的状态不会发生变化,所以多个线程可以同时读取。但在读取时,不可以写入。
  5. 当线程执行写入操作时,实例的状态就会发生变化。因此,当有一个线程正在写人时,其他线程不可以读取或写入。

6.3 Read-Write Lock模式中的角色

6.3.1 Reader(读者)

  1. Reader 角色对 SharedResource 角色执行 read 操作。

6.3.2 Writer(写者)

  1. Writer 角色对 SharedResource 角色执行 write 操作。

6.3.3 SharedResource(共享资源)

  1. SharedResource角色表示的是 Reader 角色和 Writer 角色二者共享的资源。SharedResource角色提供不修改内部状态的操作(read)和修改内部状态的操作(write)。

6.3.4 ReadWriteLock(读写锁)

  1. ReadWriteLock角色提供了SharedResource角色实现read操作和write操作时所需的锁。即实现read操作时所需的 readLock 和 readUnlock,以及实现write操作时所需的 writeLock和writeUnlock。

6.3.5 类图和Timethreads图

类图

Reader读取,Writer等待

一个Writer写入,其他Reader和Writer等待

6.4 拓展思路的要点

6.4.1 利用“读取”操作的线程之间不会冲突的特性来提高程序性能

  1. Read-Write Lock模式利用了读取操作的线程之间不会冲突的特性。由于读取操作不会修改SharedResource角色的状态,所以彼此之间无需执行互斥处理。因此多个Reader角色可以同时执行read操作,从而提高程序性能。
  2. 但性能的提升也不是这么绝对。Read-Write Lock模式能否提高程序性能,必须通过实际的测量来判定。另外,还需要考虑下面讲述的 “适合读取操作繁重时” 和 “适合读取频率比写入频率高时” 这两个大方针。

6.4.2 适合读取操作繁重时

  1. 在单纯使用Single Threaded Execution模式的情况下,就算是read操作,每次也只能运行一个线程。如果read的操作很繁重(耗费时间),那么使用Read-Write Lock模式比使用Single Threaded Execution 模式更加合适。
  2. 但是,因为Read-Write Lock模式的处理比Single Threaded Execution模式复杂,所以当read的操作很简单(不耗费时间)时,Single Threaded Execution模式反而会更加合适。

6.4.3 适合读取频率比写入频率高时

  1. Read-Write Lock模式的优点是Reader角色之间不会发生冲突。但是,如果写入处理(write)
    的频率很高,Writer角色便会频繁停止Reader角色的处理,这样就无法体现出Read-Write Lock模式的优点了。

6.6 java.util.concurrent.locks 包和 Read-Write Lock模式

6.6.1 java.util.concurrent.locks包

  1. 可用 ReadwriteLock 接口和 ReentrantReadwriteLock 类实现Read-Write Lock模式。
  2. ReentrantReadwriteLock类的主要特征如下:
    • 公平性:当创建ReentrantReadWriteLock类的实例时,我们可以选择锁的获取顺序是否要设为公平(fair)的。如果创建的实例是公平的,那么等待时间久的线程将可以优先获取锁
    • 可重入性:ReentrantReadWriteLock类的锁是可重入的(reentrant)。也就是说,Reader角色的线程可以获取“用于写入的锁”,Writer角色的线程也可以获取“用于读取的锁”。
    • 锁降级:ReentrantReadWriteLock类可以按:获取用于写入的锁->获取用于读取的锁->释放用于写入的锁对锁进行降级。但是,“用于读取的锁” 不可以升级为 “用于写入的锁”。
ReentrantLockReadWriteLock是Java中用于实现线程同步的两种锁机制。它们之间的区别如下所示: 1. 功能不同: - ReentrantLock是一个互斥锁,它只允许一个线程同时访问被保护的资源。当一个线程获取到锁后,其他线程必须等待该线程释放锁才能访问资源。 - ReadWriteLock是一个读写锁,它允许多个线程同时读取被保护的资源,但只允许一个线程进行写操作。当有线程进行写操作时,其他线程无法进行读或写操作,直到写操作完成。 2. 锁的获取方式不同: - ReentrantLock使用独占锁的方式,即只允许一个线程获取锁。 - ReadWriteLock使用共享锁和独占锁的方式,即多个线程可以同时获取读锁,但只有一个线程可以获取写锁。 3. 性能不同: - ReentrantLock在竞争激烈的情况下,由于只允许一个线程获取锁,可能会导致其他线程长时间等待,从而降低性能。 - ReadWriteLock在读多写少的情况下,由于允许多个线程同时读取,可以提高并发性能。 4. 适用场景不同: - ReentrantLock适用于对共享资源进行互斥访问的场景,例如生产者-消费者模型。 - ReadWriteLock适用于读多写少的场景,例如缓存系统。 范例:<<引用:ReentrantLockReadWriteLock的区别在于功能、锁的获取方式、性能和适用场景等方面。ReentrantLock是一个互斥锁,只允许一个线程访问被保护的资源,使用独占锁的方式。ReadWriteLock是一个读写锁,允许多个线程同时读取被保护的资源,但只允许一个线程进行写操作,使用共享锁和独占锁的方式。在竞争激烈的情况下,ReentrantLock可能会导致其他线程长时间等待,降低性能;而在读多写少的情况下,ReadWriteLock可以提高并发性能。ReentrantLock适用于对共享资源进行互斥访问的场景,而ReadWriteLock适用于读多写少的场景[^1]。>>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值