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

璧山集团网站建设傻瓜式建站软件下载

璧山集团网站建设,傻瓜式建站软件下载,在seo优化中,网站缩略图代码首先#xff0c;在AQS中#xff0c;等待队列是通过Node类来表示的#xff0c;每个Node节点包含了等待线程的信息以及等待状态。下面是Node类的部分源码#xff1a;static final class Node {// 等待状态volatile int waitStatus;// 前驱节点volatile Node prev;// 后继节点…首先在AQS中等待队列是通过Node类来表示的每个Node节点包含了等待线程的信息以及等待状态。下面是Node类的部分源码static final class Node {// 等待状态volatile int waitStatus;// 前驱节点volatile Node prev;// 后继节点volatile Node next;// 等待线程volatile Thread thread;// 等待条件Node nextWaiter;// ...省略其他代码... }从上面的代码可以看出每个Node节点都有一个指向前驱节点和后继节点的指针这样可以在O(1)时间内查找前驱和后继节点。接下来我们来看看AQS是如何使用双向链表来管理等待队列的。AQS内部有一个成员变量volatile Node head它表示等待队列的头节点。当一个线程需要等待锁或条件时它会创建一个Node节点并插入到等待队列的尾部。这个过程是通过以下方法实现的private Node addWaiter(Node mode) {// 创建一个Node节点表示当前线程Node node new Node(Thread.currentThread(), mode);// 尝试通过CAS操作将Node节点插入到等待队列的尾部Node pred tail;if (pred ! null) {node.prev pred;if (compareAndSetTail(pred, node)) {pred.next node;return node;}}enq(node);return node; } 在上面的代码中首先创建了一个Node节点表示当前线程然后尝试通过CAS操作将它插入到等待队列的尾部。如果CAS操作失败说明有其他线程正在修改等待队列此时会调用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;}}} }在enq()方法中首先获取等待队列的尾节点如果尾节点为空说明队列还没有初始化需要先创建一个空的头节点来初始化队列。如果尾节点不为空就将新的节点插入到尾节点的后面。如果CAS操作失败说明有其他线程正在修改等待队列这时需要重新尝试。当一个线程持有锁的线程释放锁时它会将等待队列的头节点出队并唤醒它的后继节点这个过程是通过以下方法实现的private void setHead(Node node) {head node;node.thread null;node.prev null; }private void unparkSuccessor(Node node) {int ws node.waitStatus;if (ws 0)compareAndSetWaitStatus(node, ws, 0);Node s node.next;if (s null || s.waitStatus 0) {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); } 在上面的代码中首先将头节点设置为当前节点然后将头节点的prev指针置为null表示它已经出队了将头节点的thread指针置为null表示当前线程不再持有锁。接下来通过unparkSuccessor()方法唤醒后继节点。这个方法中首先检查当前节点的等待状态如果它的等待状态小于0说明它是一个被取消的节点将它的等待状态置为0。然后找到当前节点的后继节点如果它不存在或者它的等待状态大于0说明它不能被唤醒这时就需要从等待队列的尾部开始往前找找到一个等待状态小于等于0的节点来唤醒。最后通过LockSupport.unpark()方法唤醒后继节点的线程。从双向链表的特性来看我认为AQS使用双向链表有三个方面的考虑。第一个方面没有竞争到锁的线程加入到阻塞队列并且阻塞等待的前提是当前线程所在节点的前置节点是正常状态这样设计是为了避免链表中存在异常线程导致无法唤醒后续线程的问题。所以线程阻塞之前需要判断前置节点的状态如果没有指针指向前置节点就需要从head节点开始遍历性能非常低。第二个方面在Lock接口里面有一个lockInterruptibly()方法这个方法表示处于锁阻塞的线程允许被中断。也就是说没有竞争到锁的线程加入到同步队列等待以后是允许外部线程通过interrupt()方法触发唤醒并中断的。这个时候被中断的线程的状态会修改成CANCELLED。被标记为CANCELLED状态的线程是不需要去竞争锁的但是它仍然存在于双向链表里面。意味着在后续的锁竞争中需要把这个节点从链表里面移除否则会导致锁阻塞的线程无法被正常唤醒。在这种情况下如果是单向链表就需要从Head节点开始往下逐个遍历找到并移除异常状态的节点。同样效率也比较低还会导致锁唤醒的操作和遍历操作之间的竞争。第三个方面为了避免线程阻塞和唤醒的开销所以刚加入到链表的线程首先会通过自旋的方式尝试去竞争锁。但是实际上按照公平锁的设计只有头节点的下一个节点才有必要去竞争锁后续的节点竞争锁的意义不大。否则就会造成羊群效应也就是大量的线程在阻塞之前尝试去竞争锁带来比较大的性能开销。所以为了避免这个问题加入到链表中的节点在尝试竞争锁之前需要判断前置节点是不是头节点如果不是头节点就没必要再去触发锁竞争的动作。所以这里会涉及到前置节点的查找如果是单向链表那么这个功能的实现会非常复杂。
http://www.hkea.cn/news/14517748/

相关文章:

  • ps网站交互设计公司邮箱地址
  • 新建网站多少钱近两年成功的网络营销案例及分析
  • 大安市建设局网站怎么做本地化网站
  • 怎么免费建立自己的网站平台宁波江北区城市建设档案馆网站
  • 如何做网站网页流程外国ps修图网站
  • 抽奖网站开发wordpress 小程序教程
  • 设计师的素材网站中国化工建设协会网站
  • 惠州模板网站建设网站建设dqcx
  • 苏州免费网站制作图片识别 在线百度识图
  • 专业网站制作公司是如何处理一个优秀网站的做游戏钓鱼网站
  • 服装网站建设论文范文做网站学什么代码
  • 企业快速建站江苏中粟建设工程有限公司网站
  • 什么是传统网站衡阳的网站建设
  • 网站哪个公司做的比较好珠海网站建设那家好
  • 遵义企业网站建设电影网站建设方案
  • 支持微信支付的网站开发刚做的网站怎么收录
  • 什么都能买到的网站python自学要多久
  • python 网站开发the author wordpress
  • php网站进后台wordpress分类主题模板下载
  • wordpress网站统计代码做驾校题目用什么网站好
  • 做网站图片切图可以用中文吗做网站赠送
  • 虹口房产网站建设app开发价格一览表
  • 湘乡网站seo个人做理财网站
  • 网站搭建上海加强经管学院网站建设
  • 织梦网站备案海口网站建设优化
  • 莱西大型网站建设环球资源网成立时间
  • 做微信网站的职位营销型网站建设市场分析
  • 动易后台 网站统计调查 报表类型怎样使用子网页怎么做
  • 网上拿货做哪个网站好网站建设的三个步骤是什么
  • asp.net门户网站项目怎么做建网站卖产品怎么样