基础篇:JAVA原子组件和同步组件 (3)

通俗解释:玩游戏时,假如主线任务需要靠完成五个小任务,主线任务才能继续进行时。此时可以用CountDownLatch,主线任务阻塞等待,每完成一小任务,就done一次计数,直到五个小任务全部被执行才能触发主线

使用示例

public static void main(String[] args) throws Exception { CountDownLatch count = new CountDownLatch(2); for (int i = 0; i < 2; i++) CompletableFuture.runAsync(() -> { try { Thread.sleep(1000); System.out.println(" CompletableFuture over "); count.countDown(); } catch (Exception e) { throw new RuntimeException(e); } }); //等待CompletableFuture线程的完成 count.await(); System.out.println(" main over "); } ---------------输出结果------------------ CompletableFuture over CompletableFuture over main over CyclicBarrier实现原理和使用场景

CyclicBarrier则是靠ReentrantLock lock和Condition trip属性来实现同步

通俗解释:CyclicBarrier需要阻塞全部线程到await状态,然后全部线程再全部被唤醒执行。想象有一个栏杆拦住五只羊,需要当五只羊一起站在栏杆时,栏杆才会被拉起,此时所有的羊都可以飞跑出羊圈

使用示例

public static void main(String[] args) throws Exception { CyclicBarrier barrier = new CyclicBarrier(2); CompletableFuture.runAsync(()->{ try { System.out.println("CompletableFuture run start-"+ Clock.systemUTC().millis()); barrier.await(); //需要等待main线程也执行到await状态才能继续执行 System.out.println("CompletableFuture run over-"+ Clock.systemUTC().millis()); }catch (Exception e){ throw new RuntimeException(e); } }); Thread.sleep(1000); //和CompletableFuture线程相互等待 barrier.await(); System.out.println("main run over!"); } ---------------输出结果------------------ CompletableFuture run start-1609822588881 main run over! CompletableFuture run over-1609822589880 StampedLock

StampedLock不是借助AQS,而是自己内部维护多个状态值,并配合cas实现的

StampedLock具有三种模式:写模式、读模式、乐观读模式

StampedLock的读写锁可以相互转换

//获取读锁,自旋获取,返回一个戳值 public long readLock() //尝试加读锁,不成功返回0 public long tryReadLock() //解锁 public void unlockRead(long stamp) //获取写锁,自旋获取,返回一个戳值 public long writeLock() //尝试加写锁,不成功返回0 public long tryWriteLock() //解锁 public void unlockWrite(long stamp) //尝试乐观读读取一个时间戳,并配合validate方法校验时间戳的有效性 public long tryOptimisticRead() //验证stamp是否有效 public boolean validate(long stamp)

使用示例

public static void main(String[] args) throws Exception { StampedLock stampedLock = new StampedLock(); long stamp = stampedLock.tryOptimisticRead(); //判断版本号是否生效 if (!stampedLock.validate(stamp)) { //获取读锁,会空转 stamp = stampedLock.readLock(); long writeStamp = stampedLock.tryConvertToWriteLock(stamp); if (writeStamp != 0) { //成功转为写锁 //fixme 业务操作 stampedLock.unlockWrite(writeStamp); } else { stampedLock.unlockRead(stamp); //尝试获取写读 stamp = stampedLock.tryWriteLock(); if (stamp != 0) { //fixme 业务操作 stampedLock.unlockWrite(writeStamp); } } } } 欢迎指正文中错误 参考文章

并发之Striped64(l累加器)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwgps.html