信号介绍
信号量,限制对共享资源访问的最大线程数量,要访问共享资源,需要先申请许可,申请到许可才能访问。访问结果了,释放许可。
案例:
3个线程:线程1,线程2,Thread-3。一个许可数为2的公平策略的信号。
线程的调用顺序如下:
线程1申请一个许可,等待几秒钟,继续执行
线程2申请2个许可,许可不足,阻塞
Thread-3申请一个许可,等待几秒钟,继续执行
线程1,Thread-3,释放许可之后,线程2可以申请许可,成功执行。
代码:
Thread-1/3
<代码>进口java.util.concurrent.Semaphore; 公共类Task1实现Runnable { 私人信号信号量; 公共Task1(信号量信号){ 这一点。信号量=信号; } @Override 公共空间run () { 尝试{ semaphore.acquire (); System.out.println (Thread.currentThread () . getname() +”获取到许可....”); thread . sleep (3000); System.out.println (Thread.currentThread () . getname() +”执行....”); }捕捉(InterruptedException e) { e.printStackTrace (); 最后}{ System.out.println (Thread.currentThread () . getname() +”释放许可....”); semaphore.release (); } } } 代码>线程2
<代码>进口java.util.concurrent.Semaphore; 公开课Task2实现Runnable { 私人信号信号量; 公共Task2(信号量信号){ 这一点。信号量=信号; } @Override 公共空间run () { 尝试{ System.out.println (Thread.currentThread () . getname() +”申请许可....”); semaphore.acquire (2); System.out.println (Thread.currentThread () . getname() +”获取到许可....”); thread . sleep (3000); System.out.println (Thread.currentThread () . getname() +”执行....”); }捕捉(InterruptedException e) { e.printStackTrace (); 最后}{ System.out.println (Thread.currentThread () . getname() +”释放许可....”); semaphore.release (2); } } } 代码>
启动文件
<代码>进口java.text.ParseException; 进口java.util.concurrent.CountDownLatch; 进口java.util.concurrent.Semaphore; 进口java.util.concurrent.locks.Condition; 进口java.util.concurrent.locks.ReentrantLock; 公开课主要{ 公共静态void main (String [] args)抛出ParseException, InterruptedException { 信号量信号量=new信号(真实); ReentrantLock锁=新的ReentrantLock(真正的); 条件条件=lock.newCondition (); 线程t1=新线程(新Task1(信号量),“线程1”); t1.start (); thread . sleep (2000); 线程t2=新线程(新Task2(信号量),线程2); 线程t3=新线程(新Task1(信号量),“Thread-3”); t2.start (); t3.start (); } } 代码>
结果:
源码分析
创建公平的信号量,就是直接修改aq的同步状态状态
线程1,申请许可,执行aq的acquireSharedInterruptibly
信号量是如何实现tryAcquireShared方法的
此时,线程1申请一个,是足够的,返回成功,然后持有许可,此时状态=1。
线程2申请2个许可,但国家是=1,不够的。
线程2会申请失败,进入doAcquireSharedInterruptibly
doAcquireSharedInterruptibly方法之前的文章也介绍过了,这里不再详细介绍,最终线程2被包装成节点放【等待队列】,同时需要设置【等待队列】头结点为信号状态,然后线程2阻塞了。
Thread-3申请一个许可,是成功的,然后持有许可,此状态=0时。
线程1、释放了许可,则国家=1;