一 . 概述
在之前我们介绍了CountDownLatch和CyclicBarrier两个类.
其中,CountDownLatch是凑足信号量启动一个线程运行,而CyclicBarrier是凑够信号量将原先阻塞的线程全部启动.
现在我们需要介绍一个信号量类---Semaphore.
说到信号量,大家都不陌生了,信号量是操作线程通信的最好方式之一了.
二 .类结构和解释
Semaphore表示一个信号量对象,其中维护一组数量,
当调用acquire的时候会获取一个信号量,当信号量不足的时候,阻塞了,直到有足够的信号量.
release()释放一个信号量.
Semaphore:
public Semaphore(int permits)
public Semaphore(int permits, boolean fair)
核心方法:
获取信号量
public void acquire()
public void release() //释放信号量
三 . 例子
我们实现我们的计数器功能,使用一个信号量来完成.
public class SemaphoreTest { static class Lock{ private Semaphore semaphore = new Semaphore(1); public void lock() throws InterruptedException { semaphore.acquire(); } public void unlock() { semaphore.release(); } } private static volatile Integer count = new Integer(0) ; public static void main(String[] args) throws Exception { final Lock lock = new Lock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { for(int x = 0 ; x<10000;x++) { try { lock.lock(); count++; } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { for(int x = 0 ; x<10000;x++) { try { lock.lock(); count++; } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("最终的结果是count="+count); } }
我们可以看到我们使用Semaohore可以完成独占锁的功能,其实它的功能更加强大,能完成共享锁的功能,其中还有公平和非公平的实现,也就是
队列的是否遵循先来后到的原则.
其中acquire一次可以抢占都个资源,而release()可以释放多个信号量.
四 . 原理
没有什么好说的,底层还是AQS实现的.
我们可以把此类看做是一个与操作系统中信号量概念一致的事物就可以了.