一文带你连结java中的同步用具类CountDownLatch
丰满欧美大爆乳性猛交

丰满欧美大爆乳性猛交

一文带你连结java中的同步用具类CountDownLatch

发布日期:2022-06-19 12:40    点击次数:188

一文带你连结java中的同步用具类CountDownLatch

一、界说

CountDownLatch的作用很轻便,即是一个好像一组线程在运转现实操作之前,必须要比及其他线程现实完才不错。咱们举一个例子来说明,在检会的技巧,憨厚必须要比及通盘人交了试卷才不错走。此时憨厚就止境于恭候线程,而学生就好比是现实的线程。

邃密无比:java中还有一个同步用具类叫做CyclicBarrier,他的作用和CountDownLatch雷同。相似是恭候其他线程都完成了,才不错进行下一步操作,咱们再举一个例子,在打王者的技巧,在开局前通盘人都必须要加载到100%才不错参预。不然通盘玩家都相互恭候。

咱们看一下永诀:CountDownLatch:一个线程(好像多个),恭候另外N个线程完成某个事情之后才调现实。CyclicBarrier:N个线程相互恭候,任何一个线程完成之前,通盘的线程都必须恭候。重要点其实就在于那N个线程(1)CountDownLatch内部N个线程即是学生,学生做结束试卷就不错走了,无须恭候其他的学生是否完成(2)CyclicBarrier内部N个线程即是通盘的游戏玩家,一个游戏玩家加载到100%还不不错,必须要比及其他的游戏玩家都加载到100%才不错开局

面前应该连结CountDownLatch的含义了吧,底下咱们使用一个代码案例来解说。

二、使用

咱们使用学生检会的案例来进行演示:

publicclassCountDownLatchTest{staticCountDownLatchcountDownLatch=newCountDownLatch(2);publicstaticvoidmain(String[]args){System.out.println("全班同学运转检会:一共两个学生");newThread(->{System.out.println("第一个学生交卷,countDownLatch减1");countDownLatch.countDown;}).start;newThread(->{System.out.println("第二个学生交卷,countDownLatch减1");countDownLatch.countDown;}).start;try{countDownLatch.await;}catch(InterruptedExceptione){e.printStackTrace;}System.out.println("憨厚盘货试卷,在此之前,惟有一个学生没交,"+"countDownLatch不为0,不成离开科场");}}

在上头,咱们界说了一个CountDownLatch, 午夜福利视频并开拓其值为2。有两个学生使用两个线程来示意,然后治安现实。终末憨厚线程(main线程)在学生线程都现实结束才不错现实。咱们来运行一边望望成果。

面前咱们应该能体会到其用法了吧。在上头咱们的恭候线程时憨厚(main线程)。

底下咱们对这个countDownLatch分析一下。为什么具有上头的特色。

三、旨趣

在上头咱们看到,CountDownLatch主要使用countDown样式进行减1操作,使用await样式进行比及操作。咱们参预到源码中望望。本源码基于jdk1.8。特在此说明。

1、countDown旨趣

/***Decrementsthecountofthelatch,releasingallwaitingthreadsif*thecountreacheszero.**

Ifthecurrentcountisgreaterthanzerothenitisdecremented.*Ifthenewcountiszerothenallwaitingthreadsarere-enabledfor*threadschedulingpurposes.**

Ifthecurrentcountequalszerothennothinghappens.*/publicvoidcountDown{sync.releaseShared(1);}

英语不好的人看起来的确是一脸懵逼,不外信号上头的英语还都是轻便的英语,约莫有趣是这么的:CountDownLatch内部保存了一个count值,通过减1操作,直到为0技巧,恭候线程才不错现实。而况通过源码也不错看到这个countDown样式其实是通过sync调用releaseShared(1)来完成的。

OK。到了这一步咱们可能会烦懑,sync是个什么鬼,releaseShared样式又是何如收场的。咱们不妨接着看源码,在CountDownLatch的着手咱们找到了谜底,久久精品亚洲中文字幕无码本来这个sync在这里界说了。

privatestaticfinalclassSyncextendsAbstractQueuedSynchronizer{privatestaticfinallongserialVersionUID=4982264981922014374L;Sync(intcount){setState(count);}intgetCount{returngetState;}protectedinttryAcquireShared(intacquires){return(getState==0)?1:-1;}protectedbooleantryReleaseShared(intreleases){//Decrementcount;signalwhentransitiontozerofor(;;){intc=getState;if(c==0)returnfalse;intnextc=c-1;if(compareAndSetState(c,nextc))returnnextc==0;}}}

在这里咱们发现接受了AbstractQueuedSynchronizer(AQS)。AQS的其中一个作用即是选藏线程景色和取得开释锁。在这里也即是说CountDownLatch使用AQS机制选藏锁景色。而releaseShared(1)样式即是开释了一个分享锁。

面前连结了吧,底层使用AQS机制调用releaseShared样式开释一个锁资源。那么恭候的样式是何如收场的呢?

2、await旨趣

publicvoidawaitthrowsInterruptedException{sync.acquireSharedInterruptibly(1);}publicbooleanawait(longtimeout,TimeUnitunit)throwsInterruptedException{returnsync.tryAcquireSharedNanos(1,unit.toNanos(timeout));}

这俩样式都是让线程恭候,第一个莫得收场为止,第二个偶然辰为止,咱们一个一个来看。

(1)await

await底层主如果acquireSharedInterruptibly样式收场的,持续跟进去望望。

publicfinalvoidacquireSharedInterruptibly(intarg)throwsInterruptedException{if(Thread.interrupted)thrownewInterruptedException;if(tryAcquireShared(arg)

这内部有两个if语句,最初第一个判断是否被中断,如果被中断了,那就抛出中断额外。然后判断刻下是否还有线程未现实,如果有那就,那就现实doAcquireSharedInterruptibly样式持续恭候。

//这是AQS内部的样式//arg在这里调用的是1,示意countDown是否减少到了0//如果到0了,那说明餍足了要求,复返1,不再恭候//如果莫得达到0,说明还有线程未现实,必须要比及通盘的线程//现实收尾才不错,复返-1,此时小于0,现实doAcquireSharedInterruptiblyprotectedinttryAcquireShared(intarg){thrownewUnsupportedOperationException;}

上头函数的有趣还是在注视内部了,底下咱们就来望望这个doAcquireSharedInterruptibly是何如收场的。

privatevoiddoAcquireSharedInterruptibly(intarg)throwsInterruptedException{finalNodenode=addWaiter(Node.SHARED);booleanfailed=true;try{for(;;){finalNodep=node.predecessor;if(p==head){intr=tryAcquireShared(arg);if(r>=0){setHeadAndPropagate(node,r);p.next=null;//helpGCfailed=false;return;}}if(shouldParkAfterFailedAcquire(p,node)&&parkAndCheckInterrupt)thrownewInterruptedException;}}finally{if(failed)cancelAcquire(node);}}

这块的代码比拟长,不外约莫有趣我不错容貌一下,他会用一个一个的节点将线程串起来等达到条款后再一个一个的叫醒。中枢即是第三行的addWaiter函数。咱们不错再跟进去望望吧。

privateNodeaddWaiter(Nodemode){Nodenode=newNode(Thread.currentThread,mode);//Trythefastpathofenq;backuptofullenqonfailureNodepred=tail;if(pred!=null){node.prev=pred;if(compareAndSetTail(pred,node)){pred.next=node;returnnode;}}enq(node);returnnode;}

你会发现这内部也使用了CAS机制。而况即是使用链表穿起来的。

(2)await(longtimeout,TimeUnitunit)

这个样式的有趣是恭候指定的时辰,如果还有线程没现实完,那就接着现实。就好比考完试了,还有同学没交试卷,此时因为到时辰了。岂论四六二十四也岂论剩下的同学是否提交,平直就走了。其底层是通过Sync的tryAcquireSharedNanos样式收场的,咱们接着参预到源码中望望。

publicfinalbooleantryAcquireSharedNanos(intarg,longnanosTimeout)throwsInterruptedException{if(Thread.interrupted)thrownewInterruptedException;returntryAcquireShared(arg)>=0