源码解析-Semaphore

创建 Semaphore 实例的时候,需要一个参数 permits,

这个基本上可以确定是设置给 AQS 的 state 的,

然后每个线程调用 acquire 的时候,执行 state = state - 1,

release 的时候执行 state = state + 1,

当然,acquire 的时候,如果 state = 0,说明没有资源了,需要等待其他线程 release。

基本操作

 

 

1.创建Semaphore对象,初始化permits

2. semaphore.acquire()  占用一个位置

3. semaphore.release() 取消一个位置   

 

Semaphore原理是AQS 可以理解成 就是多个对象共持有的一把锁,达到permits数量 再想争抢锁就要等待,持有锁的对象释放。也区分公平锁非公平锁竞争原则

 

源码解析:

1. new Semaphore()

 

  

 

 没啥好说的   初始化设置AQS的state

 

2. acquire(int permits)  占用几个空位的资源

 

acquireSharedInterruptibly()  老中断处理了

 

 

if (tryAcquireShared(arg) < 0) //说明占位失败  要么是没那么多位置给你占  要么是CAS失败了

 

 

3. tryAcquireShared()   非公平锁的实现

 

 

 

 死循环(){

获取当前的state值;

remaining = state - 想要占位数;

if(如果想要占位数>state总数  或者CAS成功 ){

  返回剩余位数;

}

}

 

4.  doAcquireSharedInterruptibly()  占位失败,加入到阻塞队列

 

 将节点封装成Node 加入到阻塞队列

for( 死循环){

  判断前直接点是不是头节点;

  如果前置节点是头节点,尝试去抢占位置,

  抢占成功了,大吉大利 队列中删除节点,结束;

  抢失败了 挂起等待唤醒。

}

finally{

  如果中途被中断了 就退出争抢 不玩了;

}

 

5. relase()  释放资源

 

 

 

 

6. tryReleaseShared()  尝试释放共享资源   改state值

 

 for(死循环){

  获取当前state值;

  next = state + 要释放的位置数;

  CAS交换

}

 

7. doReleaseShared()   唤醒所有等待的节点

 

posted @ 2020-11-13 15:50  六小扛把子  阅读(169)  评论(0)    收藏  举报