当前位置: 首页 > news >正文

优化型网站建设阿里云wordpress伪静态

优化型网站建设,阿里云wordpress伪静态,图片设计软件免费版,网站建设运行关于 AQS#xff0c;网上已经有无数的文章阐述 AQS 的使用及其源码#xff0c;所以多这么一篇文章也没啥所谓#xff0c;还能总结一下研究过的源码。源码解析和某某的使用#xff0c;大概是互联网上 Java 文章中写得最多的主题了。 AQS AQS 是 AbstractQueuedSynchronize…关于 AQS网上已经有无数的文章阐述 AQS 的使用及其源码所以多这么一篇文章也没啥所谓还能总结一下研究过的源码。源码解析和某某的使用大概是互联网上 Java 文章中写得最多的主题了。 AQS AQS 是 AbstractQueuedSynchronizer 的缩写中文翻译过来就是抽象队列同步器。ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch 都是基于 AQS。AQS 的核心思想是当线程请求获取资源时如果资源空闲则会将当前线程设置为资源的独占线程成功获得锁否则将获取锁失败的线程加入到排队队列中CLH并提供线程阻塞和线程唤醒机制。CLH 是一个虚拟的双向队列。 首先看一下 AQS 的关键属性。 // java.util.concurrent.locks.AbstractQueuedSynchronizer private transient volatile Node head; //队列的头节点 private transient volatile Node tail; //队列的尾节点 private volatile int state; //同步状态state 用于实现锁的可重入性。 0 为表示没有线程持有该锁当存在线程获取锁成功则 state 变为 1。如果是同一线程重复获得则 state如果存在线程释放锁则 state– 上面的三个属性都存在对应的以 CAS 方式进行修改的方法state 对应的是 compareAndSetState() 方法 head 对应的是 compareAndSetHead() 方法tail 对应的是 compareAndSetTail()。以 CAS 的方式修改值能避免锁的竞争。 因为请求获取锁的线程会以 Node 节点的方式在 CLH 队列中排队在分析 AQS 机制时也会大量涉及到 Node 节点所以很有必要对 Node 节点进行分析。 CLH 队列中 Node 节点。 // java.util.concurrent.locks.AbstractQueuedSynchronizer.Node volatile int waitStatus; //当前节点在队列中的状态 volatile Node prev; //前驱节点 volatile Node next; //后继节点 volatile Thread thread; //在该节点中排队的线程 Node nextWaiter; //下一个处于condition或共享状态的节点//等待锁的两种状态 static final Node SHARED new Node(); //共享 static final Node EXCLUSIVE null; //独占//waitStatus的几个值 static final int CANCELLED 1; //已取消 static final int SIGNAL -1; //后继节点的线程需要唤醒 static final int CONDITION -2; //节点处于等待队列中 static final int PROPAGATE -3; //线程处在SHARED情况下使用该字段ReentrantLock 说是研究 AQS 源码但 AQS 毕竟是一个抽象类只实现了部分方法另外一些方法会在子类中实现。所以我们也同样会涉及到 ReentrantLock 源码的研究。 ReentrantLock 的通常使用方式是 class X { private final ReentrantLock lock new ReentrantLock(); public void m() { lock.lock(); try { // ... method body } finally { lock.unlock() } } }ReentrantLock 存在两种锁公平锁FairSync和非公平锁NonfairSync默认为非公平锁。使用公平锁时线程会直接进入队列中排队只有队列中第一个线程才能获取锁使用非公平锁时线程会先尝试获取锁成功则占用锁失败则在队列排队。对于 AQS 来说公平锁和非公平锁的绝大部分方法都是共用的。 ReentrantLock 的主要方法有两个一是使用 lock() 方法加锁二是使用 unlock() 方法解锁。 加锁 非公平锁 我们首先来分析非公平锁的加锁过程。 // java.util.concurrent.locks.ReentrantLock.NonfairSync final void lock() { if (compareAndSetState(0, 1)) //通过cas方式设置同步状态setExclusiveOwnerThread(Thread.currentThread()); //成功设置为独占线程else acquire(1); //失败获取锁 }在 lock() 方法中会先尝试通过 CAS 的方式去获取锁成功则设置为独占线程否则执行 acquire() 方法。 // java.util.concurrent.locks.AbstractQueuedSynchronizer public final void acquire(int arg) { if (!tryAcquire(arg) //尝试获取锁acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 失败则添加到等待队列selfInterrupt(); }在 acquire() 方法中会再次尝试去获取锁如果失败则加入到排队队列。 // java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); }// java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire final boolean nonfairTryAcquire(int acquires) { final Thread current Thread.currentThread(); int c getState(); if (c 0) { //如果当前没有线程持有锁if (compareAndSetState(0, acquires)) { //statesetExclusiveOwnerThread(current); //将当前线程设置为独占线程return true; } } else if (current getExclusiveOwnerThread()) { //如果已有线程持有锁且当前线程为独占线程int nextc c acquires; if (nextc 0) // overflow throw new Error(Maximum lock count exceeded); setState(nextc); //state实现锁的可重入性return true; //获得锁} return false; //如果已有线程持有锁且当前线程不为独占线程则获取锁失败 }在 nonfairTryAcquire() 方法中如果资源空闲则再次尝试通过 CAS 的方式去获取锁。如果当前资源已被当前线程占用则将 state以实现锁的可重入性。 // java.util.concurrent.locks.AbstractQueuedSynchronizer#addWaiter // 设置队列尾节点 private Node addWaiter(Node mode) { Node node new Node(Thread.currentThread(), mode); //新建排队节点 Node pred tail; //pred指向尾节点if (pred ! null) { //如果Pred指针是Null说明等待队列中没有元素或者当前Pred指针和Tail指向的位置不同说明被别的线程已经修改node.prev pred; //将新建节点的prev指向predif (compareAndSetTail(pred, node)) { // 设置新建节点为尾节点pred.next node; return node; } } enq(node); return node; }//java.util.concurrent.locks.AbstractQueuedSynchronizer#enq private Node enq(final Node node) { for (;;) { Node t tail; if (t null) { //如果尾节点为空则说明队列还未初始化if (compareAndSetHead(new Node())) //初始化一个头节点tail head; } else { //如果已经初始化则设置为尾节点node.prev t; if (compareAndSetTail(t, node)) { t.next node; return t; } } } }如果尝试多次获取锁都失败则在 addWaiter() 方法中会将线程放到节点中并设置为排队队列的尾节点。 //java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueued final boolean acquireQueued(final Node node, int arg) { //是否成功获取到资源boolean failed true; try { //循环等待过程中是否中断过boolean interrupted false; for (;;) { final Node p node.predecessor(); //获取当前节点的前驱节点if (p head tryAcquire(arg)) { //如果前驱节点为头节点则尝试获取锁setHead(node); //获取锁成功设置当前节点为头节点p.next null; // help GC failed false; return interrupted; } //来到这里说明前驱节点不是头节点或者获取锁失败。判断当前节点是否要被阻塞if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt()) interrupted true; //线程中断成功} } finally { if (failed) cancelAcquire(node); } }加入到排队队列中后会在 acquireQueued() 方法中循环等待资源的获取并判断线程是否需要被阻塞直到线程获取成功或者抛出异常。 //java.util.concurrent.locks.AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire //靠前驱节点判断当前线程是否应该被阻塞 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { //获取前驱节点的状态int ws pred.waitStatus; if (ws Node.SIGNAL) //如果前驱节点处于唤醒状态 return true; if (ws 0) { //前驱节点处于取消状态 do { //向前查找取消的节点并将其从队列中删除node.prev pred pred.prev; } while (pred.waitStatus 0); pred.next node; } else { compareAndSetWaitStatus(pred, ws, Node.SIGNAL); //设置前驱节点为唤醒状态} return false; }//java.util.concurrent.locks.AbstractQueuedSynchronizer#parkAndCheckInterrupt //挂起当前线程阻塞调用栈返回当前线程的中断状态 private final boolean parkAndCheckInterrupt() { LockSupport.park(this); return Thread.interrupted(); }整一个非公平锁的加锁流程可以用如下流程图表示 #mermaid-svg-cLr9WiwPYcJzOkBW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW .error-icon{fill:#552222;}#mermaid-svg-cLr9WiwPYcJzOkBW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cLr9WiwPYcJzOkBW .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-cLr9WiwPYcJzOkBW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cLr9WiwPYcJzOkBW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cLr9WiwPYcJzOkBW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cLr9WiwPYcJzOkBW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cLr9WiwPYcJzOkBW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cLr9WiwPYcJzOkBW .marker.cross{stroke:#333333;}#mermaid-svg-cLr9WiwPYcJzOkBW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cLr9WiwPYcJzOkBW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW .cluster-label text{fill:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW .cluster-label span{color:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW .label text,#mermaid-svg-cLr9WiwPYcJzOkBW span{fill:#333;color:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW .node rect,#mermaid-svg-cLr9WiwPYcJzOkBW .node circle,#mermaid-svg-cLr9WiwPYcJzOkBW .node ellipse,#mermaid-svg-cLr9WiwPYcJzOkBW .node polygon,#mermaid-svg-cLr9WiwPYcJzOkBW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cLr9WiwPYcJzOkBW .node .label{text-align:center;}#mermaid-svg-cLr9WiwPYcJzOkBW .node.clickable{cursor:pointer;}#mermaid-svg-cLr9WiwPYcJzOkBW .arrowheadPath{fill:#333333;}#mermaid-svg-cLr9WiwPYcJzOkBW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cLr9WiwPYcJzOkBW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cLr9WiwPYcJzOkBW .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-cLr9WiwPYcJzOkBW .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-cLr9WiwPYcJzOkBW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cLr9WiwPYcJzOkBW .cluster text{fill:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW .cluster span{color:#333;}#mermaid-svg-cLr9WiwPYcJzOkBW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cLr9WiwPYcJzOkBW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 成功 失败 失败 队列中的线程去获取锁 true false 是 否 设置当前节点为头节点 如果当前节点的前驱节点为头节点且获取锁成功 返回是否被中断过 当前节点是否需要被阻塞 阻塞当前线程 将当前节点添加到队列 不为空 为空 设置当前节点为尾节点 尾节点是否为空 返回当前节点 enq 为空 不为空 尾节点是否为空 初始化一个空的头节点 设置当前节点为尾节点 返回当前节点 lock cas获取锁 设置为独占线程 尝试获取锁 公平锁 公平锁和非公平锁的流程中只有 lock() 方法和 tryAcquire() 方法存在差别。 //java.util.concurrent.locks.ReentrantLock.FairSync#lock final void lock() { acquire(1); //直接获取锁 }公平锁中会直接调用 acquire() 方法。 // java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire protected final boolean tryAcquire(int acquires) { final Thread current Thread.currentThread(); int c getState(); if (c 0) { if (!hasQueuedPredecessors() compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current getExclusiveOwnerThread()) { int nextc c acquires; if (nextc 0) throw new Error(Maximum lock count exceeded); setState(nextc); return true; } return false; } 相对于 nonfair 的 nonfairTryAcquire 方法在没有线程持有锁时增加了 hasQueuedPredecessors() 方法的判断该方法用于判断队列中是否存在线程比当前线程等待时间更长。 // java.util.concurrent.locks.AbstractQueuedSynchronizer#hasQueuedPredecessors public final boolean hasQueuedPredecessors() { Node t tail; Node h head; Node s; return h ! t ((s h.next) null || s.thread ! Thread.currentThread()); }分析一下这段代码 如果 h ! t 为 true说明队列正在初始化或者已经初始化完成。 在 h ! t 前提下如果 (s h.next) null 为 true说明队列正在初始化因为在队列初始化过程中是有可能存在 head 已经被初始化不再等于 tail 了但 head.next 还没有被设值为 node这种情况下因为队列中已经存在 Node当前线程需要加到等待队列中故返回 true。初始化过程在 AbstractQueuedSynchronizer#enq()。但如果 (s h.next) null 为 false说明队列中已经存在 Node则判断该 Node 的线程是否与当前线程相同。如果 s.thread ! Thread.currentThread() 为 true说明不相同需要进入等待队列。如果相同说明当前线程可以获取锁。 如果 h ! t 为 false说明队列为空返回 false说明可以去获得锁。 另外s h.next 这段代码获取的是 head 的下一个节点因为 head 是虚节点不存储数据真正的数据存储在 head.next。 解锁 相对于加锁过程解锁过程比较简单且公平锁和非公平锁共用同一个 lock() 方法。 // java.util.concurrent.locks.ReentrantLock#unlock public void unlock() { sync.release(1); }//java.util.concurrent.locks.AbstractQueuedSynchronizer#release public final boolean release(int arg) { if (tryRelease(arg)) { //如果锁没有被任何线程持有Node h head; if (h ! null h.waitStatus ! 0) unparkSuccessor(h); //解除后继节点的线程挂起return true; } return false; }关于代码 h ! null h.waitStatus ! 0分为以下几种情况 hnull说明头节点还未初始化。h!null h.waitStatus0说明后继节点还在运行中。因为如果节点已被取消waitStatus 会被设置为 1如果后继节点需要唤醒waitStatus 会被设置为 -1如果节点正在排队waitStatus 则会设置为 -2。如果 waitStatus 为 0说明已经处于运行中。h ! null h.waitStatus ! 0 则会去唤醒后继节点。 在 release() 方法中会先尝试去解锁如果解锁成功且后继节点需要唤醒则将后继节点取消挂起。 //java.util.concurrent.locks.ReentrantLock.Sync#tryRelease //更新state状态如果重入次数为0则将锁的独占线程设置为null protected final boolean tryRelease(int releases) { //减少可重入次数int c getState() - releases; if (Thread.currentThread() ! getExclusiveOwnerThread()) //如果当前线程不是该锁的独占线程则抛出异常throw new IllegalMonitorStateException(); boolean free false; //该锁是否已被释放if (c 0) { //如果可重入次数已为0free true; setExclusiveOwnerThread(null); //将锁的独占线程设置为null表明不再有线程持有该锁} setState(c); //修改锁的状态return free; }在 tryRelease() 方法中会去减少锁的可重入次数当可重入次数为 0 时清空锁的独占线程。 // java.util.concurrent.locks.AbstractQueuedSynchronizer#unparkSuccessor private void unparkSuccessor(Node node) { int ws node.waitStatus; //获取头节点的waitStatusif (ws 0) //如果节点的waitStatus为负数说明后继节点需要被唤醒或者正在排队compareAndSetWaitStatus(node, ws, 0); //清除节点当前的waitStatus设置为0 Node s node.next; //获取头节点的后继节点if (s null || s.waitStatus 0) { //如果节点为null或者已被取消s null; for (Node t tail; t ! null t ! node; t t.prev) //从尾节点开始向前遍历if (t.waitStatus 0) //找到队列中第一个不被取消的节点s t; } if (s ! null) //如果找到了则将该节点取消挂起LockSupport.unpark(s.thread); }在 unparkSuccessor() 方法中会从尾节点开始从后往前遍历找到队列中第一个没有被取消的节点将该节点取消挂起。 整个解锁流程可以用如下流程图表示。 #mermaid-svg-bszEqU3L6ck0yOGP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bszEqU3L6ck0yOGP .error-icon{fill:#552222;}#mermaid-svg-bszEqU3L6ck0yOGP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bszEqU3L6ck0yOGP .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-bszEqU3L6ck0yOGP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bszEqU3L6ck0yOGP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bszEqU3L6ck0yOGP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bszEqU3L6ck0yOGP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bszEqU3L6ck0yOGP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bszEqU3L6ck0yOGP .marker.cross{stroke:#333333;}#mermaid-svg-bszEqU3L6ck0yOGP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bszEqU3L6ck0yOGP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bszEqU3L6ck0yOGP .cluster-label text{fill:#333;}#mermaid-svg-bszEqU3L6ck0yOGP .cluster-label span{color:#333;}#mermaid-svg-bszEqU3L6ck0yOGP .label text,#mermaid-svg-bszEqU3L6ck0yOGP span{fill:#333;color:#333;}#mermaid-svg-bszEqU3L6ck0yOGP .node rect,#mermaid-svg-bszEqU3L6ck0yOGP .node circle,#mermaid-svg-bszEqU3L6ck0yOGP .node ellipse,#mermaid-svg-bszEqU3L6ck0yOGP .node polygon,#mermaid-svg-bszEqU3L6ck0yOGP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bszEqU3L6ck0yOGP .node .label{text-align:center;}#mermaid-svg-bszEqU3L6ck0yOGP .node.clickable{cursor:pointer;}#mermaid-svg-bszEqU3L6ck0yOGP .arrowheadPath{fill:#333333;}#mermaid-svg-bszEqU3L6ck0yOGP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bszEqU3L6ck0yOGP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bszEqU3L6ck0yOGP .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-bszEqU3L6ck0yOGP .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-bszEqU3L6ck0yOGP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bszEqU3L6ck0yOGP .cluster text{fill:#333;}#mermaid-svg-bszEqU3L6ck0yOGP .cluster span{color:#333;}#mermaid-svg-bszEqU3L6ck0yOGP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bszEqU3L6ck0yOGP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 解除后继节点的挂起 是 否 是 否 清除该节点的waitStatus状态 如果头节点需要被唤醒 如果后继节点为null或者后继节点已被取消 从尾节点开始往前遍历找到第一个不被取消的节点 如果找到了不被取消的节点则取消该节点的挂起 尝试释放锁 否 是 是 否 该线程是否持有该锁 减少可重入次数 抛出异常 可重入次数是否为0 设置该锁的独占线程为null并释放掉锁 修改该锁的状态 如果释放锁成功且后继节点需要解除挂起
http://www.w-s-a.com/news/253263/

相关文章:

  • 宁波搭建网站价格西部数码网站正在建设中是什么意思
  • 吉林省建设项目招标网站苏州网络推广定制
  • 网站域名所有权证明引流推广接单
  • 做网站百度百科孟州网站建设
  • 服务网站建设企业广州模板建站系统
  • 怎么做属于自己的免费网站浏览器游戏网址
  • 上海城乡住房建设厅网站西安网站推广慧创科技
  • 做策划网站推广怎么写简历互联网公司手机网站
  • 怎么做宣传网站网站建设采购项目合同书
  • 网站的空间和域名备案做网站要会写什么
  • wap 网站源码企业网站被转做非法用途
  • 下载网站模板怎么使用做物流网站的公司
  • 网站 商城 app 建设建设银行江苏省行网站
  • 广州网站开发建设西安广告公司联系方式
  • 怎么用腾讯云服务器做网站个人网站开发视频
  • 网站建设技术代码坦洲网站建设公司哪家好
  • 阿里云对象存储做静态网站怎样做网站性能优化
  • 怎样做理财投资网站装修平面图用什么软件简单
  • 建手机wap网站大概多少钱苏州网站设计公司有哪些
  • 网站建设需求文件学校网站建设方案及报价
  • 网站开发一般多少钱wordpress打赏赞插件
  • 做中国o2o网站领导唐山网站制作软件
  • 门户网站简介做网站一天能接多少单
  • 论坛类网站建设遵义网站制作外包
  • vps服务器购买网站小视频做网站怎么赚钱
  • 网站用图片wordpress同步发布
  • 织梦图片自适应网站源码网页美工的设计要点
  • 渝快办官方网站wordpress产品图片怎么改
  • 高端网站特色深圳建网站哪
  • 宝塔搭建网站软文小故事200字