Semaphore作用
如果限定某些资源最多有N个线程可以访问,那么超过N个则不允许再有线程来访问。
同时当现有线程结束后,就会释放,然后允许新的线程进来。
类似于锁的lock与 unlock过程 ,区别在于Semaphore多加锁和解锁是计数的。
示例:
1 2 3
| Semaphore semaphore = new Semaphore(3); semaphore.acquire(); semaphore.release();
|
Semephore构造函数传入0,也可以release进行+1
底层原理
Semaphore构造函数传递的值会保存在AQS的state变量中
调用acquire方法,尝试给state减1,如果state变为负数,就会阻塞当前线程,把当前线程作为结点插入到AQS队列中。如果state不为负数,则继续执行线程的后续代码。
调用release方法,会给state加1,如果AQS队列里有等待的线程,就唤醒等待的线程,并把结点移除队列。
3个线程交替打印123456789…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| public class SemaphoreDemo {
private static int n = 1;
public static void main(String[] args) { Semaphore s1 = new Semaphore(1); Semaphore s2 = new Semaphore(0); Semaphore s3 = new Semaphore(0); Thread t1 = new Thread() { @Override public void run() { for (int i = 0; i < 100; i++) { try { s1.acquire(); System.out.println("T1: " + n); n++; s2.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread t2 = new Thread() { @Override public void run() { for (int i = 0; i < 100; i++) { try { s2.acquire(); System.out.println("T2: " + n); n++; s3.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread t3 = new Thread() { @Override public void run() { for (int i = 0; i < 100; i++) { try { s3.acquire(); System.out.println("T3: " + n); n++; s1.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; t1.start(); t2.start(); t3.start(); } }
|