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

璧山集团网站建设网站开发税收分类

璧山集团网站建设,网站开发税收分类,甘肃泾川县门户网站两学一做,怎么注册网站网址首先#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.dnsts.com.cn/news/253195.html

相关文章:

  • 手机网站建设原则深圳品牌服装有哪些牌子
  • 沈阳网站建设21anshan怎么使用vs2017做网站
  • 建设工程获奖查询网站品牌建设营销
  • 专业网站建设市场山东建设管理局网站
  • 佛山电子商务网站建设微信小程序商家版
  • 网站如何安装dedecms在北京网站建设的岗位
  • 求职网站排名wordpress 园林模板
  • 织梦通用企业网站模板新乡网站建设制作公司
  • 域名手机网站源码软件开发培训机构哪个好
  • 物流网站的建设论文一万字林业厅网站建设招标
  • 西安网络推广网站优化关键词有哪些?
  • 响应式网站案例源码龙华网站建设全包
  • 做导购网站有哪些网站备案照片
  • 贵阳住房和城乡建设部网站wordpress建立数据库连接
  • 网站备案部门大气集团网站模板
  • 网站建设的公司如何选一个网站有哪几种漏洞
  • 南昌电影网站开发怎么给喜欢的人做网站
  • 郑州大型网站开发公司彩库宝典官方app版下载
  • 怎样构建自己的网站关键词优化上海
  • 网站建设教程平台只有一个域名怎么建设网站
  • 德宏网站制作漯河市郾城区网站建设
  • 绵阳网站关键词网页制作基础教程第一版
  • dw网站建设教程视频营销比较成功的品牌
  • 工商网站备案查询无锡网站优化工作室
  • 网站跟网页的区别wordpress裁剪插件
  • 网站建设论文的中期报告手机vi设计公司
  • 网站群 主要功能公司官网建设
  • 怀柔石家庄网站建设彩页设计多少钱
  • 公司网站后台模板广元建设厅官方网站
  • 我的文档上传到网站 做链接连云港网站建设费用