欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

并发编程之J.U.C的第一篇,

来源: javaer 分享于  点击 16734 次 点评:287

并发编程之J.U.C的第一篇,


并发编程之J.U.C

    • AQS 原理
    • ReentrantLock 原理
      • 1. 非公平锁实现原理
      • 2)可重入原理
      • 3. 可打断原理
      • 5) 条件变量实现原理
    • 3. 读写锁
      • 3.1 ReentrantReadWriteLock
    • 缓存更新策略
    • 读写锁原理

 

AQS 原理

全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架
特点 :

  • 用state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
    • getState - 获取 state 状态
    • setState - 设置 state 状态
    • compareAndSetState - cas 乐观锁机制设置 state 状态
    • 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
  • 提供了基于FIFO的等待队列,类似于 Monitor的EntryList
  • 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor的WaitSet

子类主要实现这样一些方法 (默认抛出UnsupportedOperationException)

  • tryAcquire
  • tryRelease
  • tryAcquireShard
  • tryReleaseShard
  • isHeldExclusively
    获取锁的优势
    在这里插入图片描述
    释放锁的姿势
    在这里插入图片描述

ReentrantLock 原理

在这里插入图片描述

1. 非公平锁实现原理

加锁解锁流程
先从构造器开始看,默认为非公平锁实现
在这里插入图片描述
NonfairSync 继承自 AQS
没有竞争时
在这里插入图片描述
第一个竞争出现时 :
在这里插入图片描述
Thread-1 执行了

  • 设置exclusiveOwnerThread为null
  • state = 0
    在这里插入图片描述
    当队列不为null,并且head的waitStatus = -1,进入unparkSuccessor 流程找到队列中离head最近的一个Node(没取消的),unpark恢复其运行,本例中即为Thread-1
    回到 Thread-1 的acquireQueued 流程
    在这里插入图片描述
    回到 Thread - 1的 acquireQueued 流程
    在这里插入图片描述
    如果加锁成功(没有竞争),会设置
  • exclusiveOwnerThread 为 Thread - 1,state = 1
  • head 指向刚刚 Thread - 1 所在的Node,该Node清空Thread
  • 原本的head因为从链表断开,而可被垃圾回收
    如果这时候有其它线程来竞争(非公平的体现),例如这时有Thread - 4来了
    在这里插入图片描述
    如果不巧又被 Thread - 4 占了先
  • Thread - 4被设置为 exclusiveOwnerThread,state = 1
  • Thread - 1再次进入 acquireQueued 流程,获取锁失败,重新进入 park阻塞
    加锁源码

2)可重入原理

在这里插入图片描述
在这里插入图片描述

3. 可打断原理

不可打断模式
在此模式下,即使它被打断,仍会驻留在AQS队列中,等获得锁后方能继续运行(是继续运行!只是打断标记被设置为true)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可打断模式
在这里插入图片描述
在这里插入图片描述

5) 条件变量实现原理

每个条件变量其实就对应着一个等待队列,其实现类是 ConditionObject
await 流程
开始 Thread - 0 持有锁,调用await,进入ConditionObject 的addConditionWaiter流程创建新的Node状态为 -2 (Node.CONDITION),关联Thread - 0,加入等待队列尾部
在这里插入图片描述
接下来进入AQS的fullyRelease流程,释放同步器上的锁
在这里插入图片描述
unpark AQS 队列中的下一个节点,竞争锁,假设没有其他竞争线程,那么Thread - 1竞争成功
在这里插入图片描述
park 阻塞 Thread - 0
在这里插入图片描述
signal
假设Thread - 1 要来唤醒 Thread - 0
在这里插入图片描述
进入 ConditionObject 的doSignal流程,取得等待队列中第一个 Node,即Thread - 0所在Node
在这里插入图片描述
执行transferForSignal 流程,将该Node 加入AQS队列尾部,将Thread - 0
的waitStatus改为0,Thread - 3的waitStatus改为 - 1
在这里插入图片描述
Thread - 1 释放锁,进入unlock流程。

3. 读写锁

3.1 ReentrantReadWriteLock

当读操作远远高于写操作时,这时候使用读写锁让 读-读可以并发,提高性能。
类似于数据库中的select 。。。from 。。。lock in share mode
提供一个数据容器类内部分别使用读锁保护数据的read()方法,写锁保护数据的write()方法
注意事项

  • 读锁不支持条件变量
  • 重入时升级不支持 :即持有读锁的情况下去获取写锁,会导致获取写锁永久等待
    在这里插入图片描述
  • 重入时降级支持 :即持有写锁的情况下去获取读锁
    在这里插入图片描述

缓存更新策略

更新时,是先清缓存还是先更新数据库
先清缓存
在这里插入图片描述
先更新数据库
在这里插入图片描述

读写锁原理

相关文章

    暂无相关文章
相关栏目:

用户点评