读写锁Reedtrantlock ReadWriteLock
本文最后更新于34 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

之前提到的锁基本都是排他锁,这些锁阿紫同一时刻只允许一个线程仅从访问,而ReentrantReadWriteLcok在同一时刻允许多个读线程访问,但是在写线程访问时,所有读线程和其他线程均会被阻塞。读写锁维护了一对锁,一个读锁和一个写锁。通过分离读锁和写锁,使得并发性相比一般的排他锁有很大提升。

Java并发包中提供的读写锁就是ReentrantReadWriteLock,他具有以下特性:

  • 公平性选择:支持公平和非公平的锁获取方式
  • 支持冲入:同一线程获取读锁之后能再次获取;同意线程获取写锁之后能再次获取写锁,并且还能获取读锁。
  • 锁降级:按照获取写锁,再获取读锁,再释放写锁的顺序,写锁就能降级为读锁。

读写锁的接口与示例

ReentrantReadWriteLock时接口ReadWriteLock的具体实现,该接口仅定义了两个方法:

  • readLock():获取读锁
  • WriteLock():获取写锁

其次还提供哦那个了查看内部状态的方法:

int getReadLcokCount():返回当前读锁被获取次数

int getReadHoldCount:返回当前线程获取读锁次数

Boolean isWriteLocked():判断写锁是否被获取

int getWriteHoldCount():返回放前写锁备货区次数

 

实现

读写锁状态设计

读写锁依然时组合了一个自定义的同步器(AQS)来实现同步功能,而读写状态就是其同步器的状态,同步状态state是一个int类型的整数。对于读写锁来说,必须将32位的int变量进行切割,其中高16位维护读锁,低16位维护写锁。

比如0000 0000 0000 0010 0000 0000 0000 0011

表示一个线程获取了写锁,并且重入两次写锁(总共三次),并且其获取了读锁,并重入一次读锁(总共两次)。

注意:如果一个线程想要同时拥有读锁和写锁,那么必须先获取写锁才能获取读锁。

 

写锁的获取与释放

获取:写锁是一个支持重入的皮塔索,如果当前线程已经获取了写锁,则增加写状态,如果当前线程在获取锁时,读锁或者写锁已经被获取,且该线程不是已经获取读锁或者写锁的进程,那么该进程进入等待状态。

释放:写锁每次释放则写状态减一,当写状态减为零时表示真正释放写锁。

 

读锁的获取与释放

获取:读锁时支持重入的共享锁,,他能被多个线程获取,在没有其他线程持有写锁时,读锁总能被成功获取。而获取所作的知识线程安全的增加读状态。若当前线程在获取读锁时,写锁已被其他线程获取,则该线程进入等待状态。

上文中getReadHoldCount()方法,作用是返回当前线程获取读锁的次数,但是读状态是维护所有线程获取锁次数的总和,因此每个线程各自获取读锁的次数只能保存在ThreadLocal中,由线程自身维护。

释放:和写锁一样,读锁每次释放则读状态减一,当读状态减为零时表示真正释读锁。

 

ReentrantReadWriteLock仅支持锁降级,也就是写锁降级位读锁,而不支持锁升级,也就是读锁升级为写锁。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇