J.U.C之Semaphore
一、简介
Semaphore是一个计数信号量,从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire,然后再获取许可。每个release添加一个许可,从而可能释放一个正在阻塞的获取者。
初始值为1的Semaphore可以用作互斥体(mutex),并具备不可重入的加锁语义:谁拥有了这个唯一的许可,谁就拥有了互斥锁。
构造方法可以传入一个公平参数,当为false时,线程是抢占的;当为true时,线程是公平的,按FIFO的顺序来获取许可。
二、实例
package com.mylearn.thread.tools; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * Created by IntelliJ IDEA. * User: yingkuohao * Date: 13-11-11 * Time: 下午4:05 * CopyRight:360buy * Descrption: * To change this template use File | Settings | File Templates. */ public class SemaphoreTest { public static void main(String args[]) { ExecutorService executorService= Executors.newCachedThreadPool(); Semaphore semaphore = new Semaphore(3); //三个信号量 for (int i = 0; i < 10; i++) { Thread thread = new Thread(new Task(semaphore)); //10个线程 executorService.submit(thread); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } executorService.shutdown(); } static class Task implements Runnable { private Semaphore semaphore; Task(Semaphore semaphore) { this.semaphore = semaphore; } public Semaphore getSemaphore() { return semaphore; } public void setSemaphore(Semaphore semaphore) { this.semaphore = semaphore; } public void run() { try { semaphore.acquire(); //只有三个线程可以拿到锁 System.out.println(Thread.currentThread().getName() + "dosomething!"+System.currentTimeMillis()); Thread.sleep((long) (Math.random()*1000)); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); //释放之后下一个线程才能拿到 } } } } |
三、源码分析
Semaphore.Acquire:
public void acquire() throws InterruptedException { sync.acquireSharedInterruptibly(1); } |
AQS.acquireSharedInterruptibly
public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) //根据返回的结果和0比较,如果小于0需要阻塞。 doAcquireSharedInterruptibly(arg); } |
Semaphore.sync.tryAcquireShared
protected int tryAcquireShared(int acquires) { Thread current = Thread.currentThread(); for (;;) { Thread first = getFirstQueuedThread(); if (first != null && first != current) return -1; int available = getState(); //检查信号量的计数器还有多少 int remaining = available - acquires;//计算减掉请求的数量剩余多少 if (remaining < 0 || compareAndSetState(available, remaining)) return remaining;//如果小于0则返回负数,不小于零返回剩余多少 } } |
SemaPhore.release
public void release() { sync.releaseShared(1); } |
sync.releaseShared
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); //唤醒阻塞线程 return true; } return false; } |
Sync.tryReleaseShared
protected final boolean tryReleaseShared(int releases) { for (;;) { int p = getState(); if (compareAndSetState(p, p + releases)) //CAS成功,返回true return true; } } |