并发编程学习笔记(十八、Semaphore源码分析)

目录:

  • Semaphore简介
  • 内部类(Sync、NonfairSync、FairSync)
  • 属性及构造器
  • 其它方法

Semaphore简介

Semaphore是信号量,它是synchronized的加强版,作用是控制线程的并发数量。就这一点而言,单纯的synchronized关键字是实现不了的。

内部类(Sync、NonfairSync、FairSync)

1、Sync:

 1 abstract static class Sync extends AbstractQueuedSynchronizer {
 2     private static final long serialVersionUID = 1192457210091910933L;
 3 
 4     /**
 5      * Sync构造函数,用于初始化许可证数量
 6      */
 7     Sync(int permits) {
 8         setState(permits);
 9     }
10 
11     final int getPermits() {
12         return getState();
13     }
14 
15     /**
16      * 非公平锁的共享实现
17      */
18     final int nonfairTryAcquireShared(int acquires) {
19         for (;;) {
20             int available = getState();
21             // 剩余许可证数量,每次加锁成功将其减少
22             int remaining = available - acquires;
23             // 当许可证数量小于0 || CAS将实际许可证数量更新成剩余许可证数量
24             if (remaining < 0 ||
25                 compareAndSetState(available, remaining))
26                 return remaining;
27         }
28     }
29 
30     /**
31      * 释放资源的共享实现(增加许可证数量)
32      */
33     protected final boolean tryReleaseShared(int releases) {
34         for (;;) {
35             int current = getState();
36             // 获取拥有许可证数量(当前剩余 + 释放数量)
37             int next = current + releases;
38             if (next < current) // overflow
39                 throw new Error("Maximum permit count exceeded");
40             // CAS更新拥有许可证数量
41             if (compareAndSetState(current, next))
42                 return true;
43         }
44     }
45 
46     /**
47      * 减少许可证数量
48      */
49     final void reducePermits(int reductions) {
50         for (;;) {
51             int current = getState();
52             int next = current - reductions;
53             if (next > current) // underflow
54                 throw new Error("Permit count underflow");
55             if (compareAndSetState(current, next))
56                 return;
57         }
58     }
59 
60     /**
61      * 获取剩余许可证数量
62      */
63     final int drainPermits() {
64         for (;;) {
65             int current = getState();
66             if (current == 0 || compareAndSetState(current, 0))
67                 return current;
68         }
69     }
70 }

2、NonfairSync:

 1 static final class NonfairSync extends Sync {
 2     private static final long serialVersionUID = -2694183684443567898L;
 3 
 4     NonfairSync(int permits) {
 5         super(permits);
 6     }
 7 
 8     protected int tryAcquireShared(int acquires) {
 9         return nonfairTryAcquireShared(acquires);
10     }
11 }

3、FairSync:

 1 static final class FairSync extends Sync {
 2     private static final long serialVersionUID = 2014338818796000944L;
 3 
 4     FairSync(int permits) {
 5         super(permits);
 6     }
 7 
 8     protected int tryAcquireShared(int acquires) {
 9         for (;;) {
10             // 公平锁的唯一区别就是只有当不存在等待时间比你长的线程时才会加锁,否则返回-1
11             if (hasQueuedPredecessors())
12                 return -1;
13             int available = getState();
14             int remaining = available - acquires;
15             if (remaining < 0 ||
16                 compareAndSetState(available, remaining))
17                 return remaining;
18         }
19     }
20 }

属性及构造器

1、属性:

1 private final Sync sync;

2、构造器:

1 public Semaphore(int permits) {
2     sync = new NonfairSync(permits);
3 }
4 
5 public Semaphore(int permits, boolean fair) {
6     sync = fair ? new FairSync(permits) : new NonfairSync(permits);
7 }

构造器同ReentrantLock,默认非公平实现方式。

其它方法

其它的一些函数都比较简单,只要你把之前的AQS看懂你就可以很轻松的了解。

如:

  • java.util.concurrent.Semaphore#acquire();
  • java.util.concurrent.Semaphore#acquire(int);
  • java.util.concurrent.Semaphore#release();
  • 等等。
posted @ 2020-06-25 20:01  被猪附身的人  阅读(156)  评论(0编辑  收藏  举报