多线程(十三,aq原理信号信号量)

  

信号介绍

  

信号量,限制对共享资源访问的最大线程数量,要访问共享资源,需要先申请许可,申请到许可才能访问。访问结果了,释放许可。

  

案例:

  

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原理信号信号量)

  

源码分析

  

创建公平的信号量,就是直接修改aq的同步状态状态

  

多线程(十三,aq原理信号信号量)

  

线程1,申请许可,执行aq的acquireSharedInterruptibly

  

多线程(十三,aq原理信号信号量)

  

信号量是如何实现tryAcquireShared方法的

  

多线程(十三,aq原理信号信号量)
此时,线程1申请一个,是足够的,返回成功,然后持有许可,此时状态=1。

  

线程2申请2个许可,但国家是=1,不够的。

  

线程2会申请失败,进入doAcquireSharedInterruptibly

  

多线程(十三,aq原理信号信号量)

  

doAcquireSharedInterruptibly方法之前的文章也介绍过了,这里不再详细介绍,最终线程2被包装成节点放【等待队列】,同时需要设置【等待队列】头结点为信号状态,然后线程2阻塞了。

  

Thread-3申请一个许可,是成功的,然后持有许可,此状态=0时。

  

线程1、释放了许可,则国家=1;

  

多线程(十三,aq原理信号信号量)

多线程(十三,aq原理信号信号量)