一、把我能想到的写下来

1.LockSupport 类

    JUC中有个很重要的工具类 LockSupport 类,每个调用这个方法的线程会对应一个许可证。默认情况下,线程是没有这个许可证的。它提供 park() 和 unpark() 方法,在并发包中用于对线程进行阻塞。
    park()方法:如果线程有许可证,就直接返回,否则会将线程阻塞挂起。
    unpark()方法:给线程许可证。如果之前线程因为 park() 方法被挂起,就会返回。
    park(long nanos)带参数时,是在nanos 时间后,线程会自动唤醒,不再阻塞。
    还有 park(Blocker blocker)方法,通过 jstatck ??? 可以在控制台查看阻塞原因。

(有无实现类???)
    

2.同步队列AQS: AbstractQueueSynchronzier

    这是个抽象类,它的实现类有 ReetrantLock(可重入锁)、ReadWriteLock(读写锁)等。数据结构是双向队列(链表形式,有 prev 和 next ),有内部类 Node和ConditionObject ,Node节点类型的变量 head指向队头, tail 指向队尾 。通过访问资源是独占的或是共享的,节点可分为 独占式 : exclusive 和 共享式 : shared ,同步队列中的节点类型有 :cancelled 已取消的、condition 在条件队列中等待的、waiting 需要被唤醒的。
    类图:
Java并发编程总结 [6] 并发包中的并发锁 原理剖析
    AQS 类中维护的单一的状态变量 state 变量十分重要,(是不是用来保证同步???)

    在不同子类中意义不同,比如在 独占锁 ReetrantLock 中,如果当前资源没有被任何线程持有,第一个线程访问资源,会标记这个线程,并且将 state 由 0 置为 1 ,如果这个线程还访问同步块,那么就会给 state +1 。

    如果用的是独占性资源,调用 acquire() 方法,首先会去调用 tryAcquire() 方法,修改 state 值,如果成功 ,就返回资源,否则,就生成一个 WAITING 类型的节点,加到同步队列队尾,并调用 LockSupport类的 park()方法将自己挂起。
    如果是共享性资源,调用的是acuqireShared() 方法。
    如果用的是独占性资源,调用 release()方法,首先会释放锁(???),那么这时需要个线程来用资源,所以会调用 tryAcquire() 方法,从同步队列【需要被唤醒的节点们】中出队一个节点,调用 LockSupport 类的 unpark() 方法,使该线程拥有许可证。
(这个锁是不是 对象的监视器锁???? ???)

    子类需要覆写 tryAcquire 方法。

    LockSupport 类的内部类 ConditionObject 是用来实现同步的,通过 AQS.Condition() ,可以产生一个 ConditionObject 对象,一个 AQS 对象可以对应很多个 ConditionObject 对象,而且 每个 ConditionObject 都对应一个 等待队列,是单向的,节点:Node 类型,由 firstWaier 和 lastWaiter 分别表示 队头、队尾 。

    lock() + await() + signal() / signalAll() + unlock() 就相当于 之前 synchronized + Object类的 wait() + notify/ notify 。 调用lock() 相当于进入同步块, await() 相当于阻塞线程,在另一个线程中可以通过 signal() 唤醒线程。

相关文章:

  • 2021-09-13
  • 2021-12-16
  • 2021-06-29
  • 2021-06-02
  • 2021-11-29
  • 2022-01-10
  • 2022-01-29
  • 2021-11-11
猜你喜欢
  • 2021-07-26
  • 2021-10-07
  • 2022-12-23
  • 2021-10-06
  • 2021-07-11
  • 2021-10-27
相关资源
相似解决方案