JAVA并发笔记

重入锁的特性, 避免死锁, 如果有锁的话, 不用重新加锁, 直接增加锁的次数..

Synchronize, ReentrantLock都是重入锁.

 

读写锁, ReentrantReadWriteLock里面有两把锁, 读锁和写锁,适用于读多写少的情景.

读->读会共享

读->写 互斥

写->写 互斥.

 

AQS: 

全称 AbstractQueuedSynchronizer,它 是一个同步工具也是 Lock 用来实现线程同步的核心组件。

AQS 的功能分为两种:独占和共享

I.AQS的state(int类型,32位)

用来描述有多少线程获持有锁。
  • 独占锁的时代这个值通常是0或者1, 对于可重入锁,一个线程可多次进入,每次进入state+1
  • 共享锁的时代就是持有锁的数量。
  • tryAcquire()和tryRelease()其实就是尝试获取状态位state的修改权限并设置独占Thread

waitStatus 状态:

变量waitStatus则表示当前被封装成Node结点的等待状态,共有4种取值CANCELLED、SIGNAL、CONDITION、PROPAGATE。

  • CANCELLED:值为1,在同步队列中等待的线程等待超时或被中断,需要从同步队列中取消该Node的结点,其结点的waitStatus为CANCELLED,即结束状态,进入该状态后的结点将不会再变化。

  • SIGNAL:值为-1,被标识为该等待唤醒状态的后继结点,当其前继结点的线程释放了同步锁或被取消,将会通知该后继结点的线程执行。说白了,就是处于唤醒状态,只要前继结点释放锁,就会通知标识为SIGNAL状态的后继结点的线程执行。

  • CONDITION:值为-2,与Condition相关,该标识的结点处于等待队列中,结点的线程等待在Condition上,当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁。

  • PROPAGATE:值为-3,与共享模式相关,在共享模式中,该状态标识结点的线程处于可运行状态。

  • 0状态:值为0,代表初始化状态。

 

 

AQS 队列内部维护的是一个 FIFO 的双向链表,这种结构的特点是每个数据结构都有两个指针,分别指向直接的后继节点和直接前驱节点。所以双向链表可以从任 意一个节点开始很方便的访问前驱和后继。每个 Node 其实是由线程封装,当线 程争抢锁失败后会封装成 Node 加入到 ASQ 队列中去;当获取锁的线程释放锁以 后,会从队列中唤醒一个阻塞的节点(线程)。

 

Condition主要是为了代替Object 监视器方法(wait、notify 和 notifyAll)。Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
Lock提供了比synchronized更加强大、灵活的锁机制,它从某种程度上来说替代了synchronized方式的使用

 

参考:

https://www.cnblogs.com/waterystone/p/4920797.html

https://www.jianshu.com/p/9e6e84f15b95?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

 

posted @ 2019-05-21 16:01  龘人上天  阅读(160)  评论(0编辑  收藏  举报