并发工具的使用以及原理

匿名 (未验证) 提交于 2019-12-03 00:00:02

Condition

ConditionWait

public class ConditionDemoWait implements Runnable{   private Lock lock;  private Condition condition;   public ConditionDemoWait(Lock lock,   Condition condition){     this.lock=lock;     this.condition=condition;   }   @Override   public void run() {     System.out.println("begin -ConditionDemoWait");     ry {       lock.lock();       condition.await();       System.out.println("end -ConditionDemoWait");     } catch (InterruptedException e) {       e.printStackTrace();     }finally {       lock.unlock();     }  } }

ConditionSignal

public class ConditionDemoSignal implements Runnable{   private Lock lock;   private Condition condition;   public ConditionDemoSignal(Lock lock,Condition condition){     this.lock=lock;     this.condition=condition;   }   @Override   public void run() {     System.out.println("begin -ConditionDemoSignal");     try {       lock.lock();       condition.signal();System.out.println("end -       ConditionDemoSignal");     }finally {       lock.unlock();     }   } }

condition.await
public final void await() throws InterruptedException {   if (Thread.interrupted()) //表示 await 允许被中断     throw new InterruptedException();   Node node = addConditionWaiter(); //创建一个新的节点,节点状态为 condition,采用的数据结构仍然是链表   int savedState = fullyRelease(node); //释放当前的锁,得到锁的状态,并唤醒 AQS 队列中的一个线程   int interruptMode = 0;   //如果当前节点没有在同步队列上,即还没有被 signal,则将当前线程阻塞   while (!isOnSyncQueue(node)) {//判断这个节点是否在 AQS 队列上,第一次判断的是 false,因为前面已经释放锁了     LockSupport.park(this); //通过 park 挂起当前线程     if ((interruptMode =checkInterruptWhileWaiting(node)) != 0)       break;   }   // 当这个线程醒来,会尝试拿锁, 当 acquireQueued返回 false 就是拿到锁了.   // interruptMode != THROW_IE -> 表示这个线程没有成功将 node 入队,但 signal 执行了 enq 方法让其入队了.   // 将这个变量设置成 REINTERRUPT.   if (acquireQueued(node, savedState) && interruptMode != THROW_IE)     interruptMode = REINTERRUPT;   // 如果 node 的下一个等待者不是 null, 则进行清理,清理 Condition 队列上的节点.   // 如果是 null ,就没有什么好清理的了.   if (node.nextWaiter != null) // clean up if     cancelled     unlinkCancelledWaiters();   // 如果线程被中断了,需要抛出异常.或者什么都不做   if (interruptMode != 0)     reportInterruptAfterWait(interruptMode); }

addConditionWaiter

private Node addConditionWaiter() {   Node t = lastWaiter;   // 如 果 lastWaiter 不 等 于 空 并 且waitStatus 不等于 CONDITION 时,把冲好个节点从链表中移除  if (t != null && t.waitStatus !=Node.CONDITION) {     unlinkCancelledWaiters();     t = lastWaiter;   }   //构建一个 Node,waitStatus=CONDITION。这里的链表是一个单向的,所以相比 AQS 来说会简单很多   Node node = new Node(Thread.currentThread(),Node.CONDITION);   if (t == null)     firstWaiter = node;   else     t.nextWaiter = node;   lastWaiter = node;   return node; }

fullyRelease

final int fullyRelease(Node node) {   boolean failed = true;   try {     int savedState = getState();     //获得重入的次数     if (release(savedState)) {//释放锁并且唤醒下一个同步队列中的线程       failed = false;     return savedState;     } else {       throw new IllegalMonitorStateException();     }  } finally {     if (failed)       node.waitStatus =Node.CANCELLED;   } }

isOnSyncQueue

final boolean isOnSyncQueue(Node node) {   if (node.waitStatus ==Node.CONDITION || node.prev == null)     return false;   if (node.next != null) // If hassuccessor, it must be on queue     return true;   return findNodeFromTail(node); }

Condition.signal

public final void signal() {   if (!isHeldExclusively()) //先判断当前线程是否获得了锁,这个判断比较简单,直接用获得锁的线程和当前线程相比即可    throw new IllegalMonitorStateException();   Node first = firstWaiter; // 拿到 Condition队列上第一个节点   if (first != null)     doSignal(first); }

Condition.doSignal

private void doSignal(Node first) {   do {     //从 Condition 队列中删除 first 节点     if ( (firstWaiter = first.nextWaiter)== null)       lastWaiter = null; // 将 next 节点设置成 nullfirst.nextWaiter = null;   } while (!transferForSignal(first) &&(first = firstWaiter) != null); }

AQS.transferForSignal

final boolean transferForSignal(Node node){  if (!compareAndSetWaitStatus(node,     Node.CONDITION, 0))//更新节点的状态为 0,如果更新失败,只有一种可能就是节点被 CANCELLED 了   return false;   Node p = enq(node);//调用 enq,把当前节点添加到AQS 队列。并且返回返回按当前节点的上一个节点,也就是原tail 节点   int ws = p.waitStatus;// 如果上一个节点的状态被取消了, 或者尝试设置上一个节点的状态为 SIGNAL 失败了(SIGNAL 表示: 他的 next节点需要停止阻塞),   if (ws > 0|| !compareAndSetWaitStatus(p, ws,Node.SIGNAL))     LockSupport.unpark(node.thread); // 唤醒节点上的线程.   return true; //如果 node 的 prev 节点已经是signal 状态,那么被阻塞的 ThreadA 的唤醒工作由 AQS 队列来完成 }

public final void await() throws InterruptedException {   if (Thread.interrupted())     throw new         InterruptedException();   Node node =addConditionWaiter();   int savedState =fullyRelease(node);   int interruptMode = 0;   while (!isOnSyncQueue(node)) {     LockSupport.park(this);     if ((interruptMode =checkInterruptWhileWaiting(node)) != 0)       break;   }   if (acquireQueued(node,savedState) && interruptMode !=THROW_IE)     interruptMode = REINTERRUPT;   if (node.nextWaiter != null) // clean up if cancelled     unlinkCancelledWaiters();   if (interruptMode != 0)     reportInterruptAfterWait(interruptMode); }

checkInterruptWhileWaiting

private int checkInterruptWhileWaiting(Node node) {   return Thread.interrupted() ?(transferAfterCancelledWait(node) ?THROW_IE : REINTERRUPT) :0; } final boolean transferAfterCancelledWait(Node node) {//使用 cas 修改节点状态,如果还能修改成功,说明线程被中断时,signal 还没有被调用。 // 这里有一个知识点,就是线程被唤醒,并不一定是在 java 层面执行了locksupport.unpark,也可能是调用了线程的 interrupt()方法,这个方法会更新一个中断标识,并且会唤醒处于阻塞状态下的线程。   if(compareAndSetWaitStatus(node,Node.CONDITION, 0)) {     enq(node); //如果 cas 成功,则把node 添加到 AQS 队列     return true;   } //如果 cas 失败,则判断当前 node 是否已经在 AQS 队列上,如果不在,则让给其他线程执行 //当 node 被触发了 signal 方法时,node 就会被加到 aqs 队列上   while (!isOnSyncQueue(node))//循环检测 node 是否已经成功添加到 AQS 队列中。如果没有,则通过 yield,     Thread.yield();   return false; }

acquireQueued

private void reportInterruptAfterWait(int interruptMode) throws InterruptedException {   if (interruptMode == THROW_IE)       throw new           InterruptedException();   else if (interruptMode ==REINTERRUPT)     selfInterrupt(); }

CountDownLatch

public static void main(String[] args) throws InterruptedException {   CountDownLatch countDownLatch=new CountDownLatch(3);   new Thread(()->{    System.out.println(""+Thread.currentThread().getName()+"-执行中");     countDownLatch.countDown();     System.out.println(""+Thread.currentThread().getName()+"-执行完毕");   },"t1").start();   new Thread(()->{    System.out.println(""+Thread.currentThread().getName()+"-执行中");     countDownLatch.countDown();     System.out.println(""+Thread.currentThread().getName()+"-执行完毕");   },"t2").start();   new Thread(()->{     System.out.println(""+Thread.currentThread().getName()+"-执行中");     countDownLatch.countDown();System.out.println(""+Thread.currentThread().getName()+"-执行完毕");   },"t3").start();   countDownLatch.await();   System.out.println("所有线程执行完毕"); }

static CountDownLatch countDownLatch=new CountDownLatch(1); @Override public void run() {   try {     countDownLatch.await();     //TODO   } catch (InterruptedException e){     e.printStackTrace();   }   System.out.println("ThreadName:"+Thread.currentThread().getName()); } public static void main(String[]args) throws InterruptedException {   for(int i=0;i<1000;i++){     new Demo().start();  }   countDownLatch.countDown(); }

CountDownLatch

acquireSharedInterruptibly

public final void acquireSharedInterruptibly(int arg) throws InterruptedException {   if (Thread.interrupted())     throw new InterruptedException();   if (tryAcquireShared(arg) < 0) //state 如果不等于 0,说明当前线程需要加入到共享锁队列中     doAcquireSharedInterruptibly(arg); }

doAcquireSharedInterruptibly

private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {  final Node node = addWaiter(Node.SHARED);     //创建一个共享模式的节点添加到队列中   boolean failed = true;   try {     for (;;) {       final Node p = node.predecessor();       if (p == head) {         int r = tryAcquireShared(arg);//就判断尝试获取锁         if (r >= 0) {//r>=0 表示获取到了执行权限,这个时候因为 state!=0,所以不会执行这段代码           setHeadAndPropagate(node, r);           p.next = null; // help GC           failed = false;           return;        }       }       //阻塞线程       if (shouldParkAfterFailedAcquire(p,node) &&parkAndCheckInterrupt())        throw newInterruptedException();     }   } finally {     if (failed)       cancelAcquire(node);   } }

CountDownLatch.countDown

public final boolean releaseShared(int arg) {   if (tryReleaseShared(arg)) {     doReleaseShared();     return true;   }   return false; } //用自旋的方法实现 state 减 1protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero   for (;;) {     int c = getState();     if (c == 0)       return false;     int nextc = c-1;     if (compareAndSetState(c,nextc))       return nextc == 0;   } }

AQS. doReleaseShared

private void doReleaseShared() {   for (;;) {     Node h = head;     if (h != null && h != tail){       int ws = h.waitStatus;       if (ws == Node.SIGNAL) {         if(!compareAndSetWaitStatus(h,Node.SIGNAL, 0))           continue;         // loop to recheck cases         unparkSuccessor(h);       }       // 这个 CAS 失败的场景是:执行到这里的时候,刚好有一个节点入队,入队会将这个 ws 设置为 -1       else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))         continue;         // loop on failed CAS     }     // 如果到这里的时候,前面唤醒的线程已经占领了 head,那么再循环     // 通过检查头节点是否改变了,如果改变了就继续循环     if (h == head)       // loop if head changed       break;   } }

private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {   final Node node =addWaiter(Node.SHARED);   boolean failed = true;   try {     for (;;) {//被唤醒的线程进入下一次循环继续判断       final Node p =node.predecessor();       if (p == head) {         int r =tryAcquireShared(arg);         if (r >= 0) {           setHeadAndPropagate(node, r);p.next = null; //把当前节点移除 aqs 队列           failed = false;           return;         }       }       if(shouldParkAfterFailedAcquire(p,node) && parkAndCheckInterrupt())         throw new InterruptedException();     }   } finally {     if (failed)       cancelAcquire(node);   } }

setHeadAndPropagate

ThreadB
private void setHeadAndPropagate(Node node, int propagate) {   Node h = head; // Record old head for check below   setHead(node);   if (propagate > 0 || h == null|| h.waitStatus < 0 ||(h = head) == null ||h.waitStatus < 0) {     Node s = node.next;     if (s == null ||s.isShared())       doReleaseShared();   }}

Semaphore

public class Test {   public static void main(String[] args) {     Semaphore semaphore=new Semaphore(5);     for(int i=0;i<10;i++){       new Car(i,semaphore).start();     }   }   static class Car extends Thread{     private int num;     private Semaphore semaphore;     public Car(int num, Semaphore semaphore) {       this.num = num;       his.semaphore = semaphore;     }     public void run(){       try {         semaphore.acquire();//获取一个许可         System.out.println("第"+num+"占用一个停车位");TimeUnit.SECONDS.sleep(2);         System.out.println("第"+num+"俩车走喽");         semaphore.release();       } catch (InterruptedException e) {         e.printStackTrace();       }     }   } }

FairSync

static final class FairSync extends Sync {   private static final long serialVersionUID = 2014338818796000944L;   FairSync(int permits) {     super(permits);   }   protected int tryAcquireShared(int acquires) {     for (;;) {// 区别就在于是不是会先判断是否有线程在排队,然后才进行 CAS 减操作       if(hasQueuedPredecessors())         return -1;       int available = getState();       int remaining = available- acquires;       if (remaining < 0 ||compareAndSetState(available,remaining))       return remaining;     }   } }

NofairSync

static final class NonfairSync extends Sync {   private static final long serialVersionUID = -2694183684443567898L;   NonfairSync(int permits) {     super(permits);   }   protected int tryAcquireShared(int acquires) {     return nonfairTryAcquireShared(acquires);   } } final int nonfairTryAcquireShared(int acquires) {   for (;;) {     int available = getState();int remaining = available -acquires;     if (remaining < 0 || compareAndSetState(available,remaining))       return remaining; } }

CyclicBarrier

DataImportThread

public class DataImportThread extends Thread{   private CyclicBarrier cyclicBarrier;   private String path;   public DataImportThread(CyclicBarrier cyclicBarrier, String path) {     this.cyclicBarrier =cyclicBarrier;     this.path = path;  }   @Override   public void run() {     System.out.println("开始导入:"+path+"位置的数据");     try {       cyclicBarrier.await();//阻塞     } catch(InterruptedException e) {       e.printStackTrace();     } catch(BrokenBarrierException e) {       e.printStackTrace();     }   } }

CycliBarrierDemo

public class CycliBarrierDemo extends Thread{  @Override   public void run() {     System.out.println("开始进行数据分析");   }   public static void main(String[] args) {     CyclicBarrier cycliBarrier=new CyclicBarrier(3,newCycliBarrierDemo());     new Thread(new DataImportThread(cycliBarrier,"file1")).start();     new Thread(new DataImportThread(cycliBarrier,"file2")).start();     new Thread(new DataImportThread(cycliBarrier,"file3")).start();} }

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!