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

网站被黑是怎么回事啊建筑考试培训网

网站被黑是怎么回事啊,建筑考试培训网,桂林生活网官网,wordpress连续照片 主题Semaphore基本使用场景 Semaphore的基本使用场景是限制一定数量的线程能够去执行. 举个简单的例子: 一个单向隧道能同时容纳10个小汽车或5个卡车通过(1个卡车等效与2个小汽车), 而隧道入口记录着当前已经在隧道内的汽车等效比重. 比如1个小汽车和1个卡车, 则隧道入口显示3. 若… Semaphore基本使用场景 Semaphore的基本使用场景是限制一定数量的线程能够去执行. 举个简单的例子: 一个单向隧道能同时容纳10个小汽车或5个卡车通过(1个卡车等效与2个小汽车), 而隧道入口记录着当前已经在隧道内的汽车等效比重. 比如1个小汽车和1个卡车, 则隧道入口显示3. 若隧道入口显示10表示已经满了. 当汽车驶出隧道之后, 隧道入口显示的数字则会相应的减小. 于这个示例相符合场景非常适合用信号量. Semaphore在构造的时候, 可以传入一个int. 表示有多少许可(permit). 线程获取锁的时候, 要告诉信号量使用多少许可(类比与小汽车和卡车), 当线程要使用的许可不足时, 则调用的线程则会被阻塞. 可以和上面简单的举例进行初步理解. Semaphore - 信号量 下面是简单代码示范 public static void main(String[] args) {// 表示有2个许可.Semaphore sem new Semaphore(2);for (int i 0; i 3; i) {new Thread(() - {try {// 默认使用一个许可.sem.acquire();System.out.println(Thread.currentThread() I get it.);TimeUnit.SECONDS.sleep(3);System.out.println(Thread.currentThread() I release it.);} catch (InterruptedException e) {e.printStackTrace();} finally {sem.release();}}).start();} }代码输出入下: Thread[Thread-0,5,main] I get it. Thread[Thread-1,5,main] I get it. Thread[Thread-1,5,main] I release it. Thread[Thread-0,5,main] I release it. Thread[Thread-2,5,main] I get it. Thread[Thread-2,5,main] I release it.上述大致可以分为以下三步: 第一步: 首先线程0和1, 获取锁. 线程3被被阻塞.第二步: 3秒过后, 线程0和线程1分别释放锁,第三步: 线程2可以获得到锁. Semaphore获取锁流程 Semaphore可以有4个方式获得锁. acquire() 线程占用一个许可.acquire(int) 线程占用int个许可acquireUninterruptibly() 线程占用一个许可, 调用不可以打断acquireUninterruptibliy(int) 线程占用int个许可,调用并且不可打断 4个方法只有细微的不同, 这里用 acquire() 用来分析, 其他的可以自行分析. acquire 方法 调用Semaphore#acquire() 方法, 它本质上是调用的AQS#acquireSharedInterruptibly(int), 参数为1. // arg 等于 1 public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();// 关于tryAcquireShared,Semaphore有两种实现// 一种是公平锁,另一种是非公平锁. 这分析非公平锁.if (tryAcquireShared(arg) 0)// 调用 AQS#doAcquireSharedInterruptibly(1) 方法doAcquireSharedInterruptibly(arg); }上面代码中, 因为AQS规定tryAcquireShared方法要由实现方覆写. 所以在Semaphore中存在两个覆写, 一个是公平锁的覆写, 另一个是非公平锁的覆写. 这里选择以非公平锁来阅读. 因为日常使用较多(可能是无意识的,构造方法只需要传入一个int). // NonfairSync#tryAcquireShared 方法. // 注意: NonfairSync extends Sync !!! protected int tryAcquireShared(int acquires) {return nonfairTryAcquireShared(acquires); }// Sync#nonfairTryAcquireShared 方法 int nonfairTryAcquireShared(int acquires) {// 当多线程竞争比较激烈, 该for循环会进行多次.for (;;) {// 获取当前状态int available getState();// 判断剩余允许线程int remaining available - acquires;// 通过CAS保证多线程操作.// 最后返回剩余. 假设当前剩余2个. 要使用1个. // if执行(没有其他线程竞争)完成, 则最后返回1个.if (remaining 0 ||compareAndSetState(available, remaining))return remaining;} }doAcquireSharedInterruptibly 方法 假设上面方法 getState() 方法返回0, 期望使用1个, 则计算得到remaining -1, 则最后返回-1. 因此会进入到下面的方法doAcquireSharedInterruptibly(int) // 假设传入的参数为1. private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {// 将调用线程封装了共享型Node, 加入到双向链表的队尾final Node node addWaiter(Node.SHARED);boolean failed true;try {for (;;) {// 记录node的前任final Node p node.predecessor();// 前任是头节点, 则尝试去获锁if (p head) {int r tryAcquireShared(arg);// 获锁成功,设置头节点,并且进行传播if (r 0) {setHeadAndPropagate(node, r);p.next null; // help GCfailed false;return;}}// 获锁失败, 判断是否进行睡眠, 若不睡眠就进行下次循环.if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);} }获取锁流程总结 Semaphore获取锁的过程总结为如下: 判断是否满足获取锁条件, 关键方法nonfairTryAcquireShared.若获取锁成功,则也会修改state.若获取锁失败,关键方法doAcquireSharedInterruptibly阻塞的获取锁. 添加到双向链表若是头节点后继, 则尝试获取锁, 否者则判断进入睡眠等待唤醒, 唤醒后继续执行3.2若不进入睡眠,则直接运行到3.2步 Semaphore释放锁流程 Semaphore释放锁两个方法. release() 释放一个许可release(int) 释放int个许可 该两个方法都会调用AQS#releaseShared(int)方法, 使用release()方法,则参数为1, 使用release(int)方法, 则参数为int. releaseShared 方法 // 释放共享锁 public final boolean releaseShared(int arg) {// 调用Semaphore#tryReleaseShared方法.if (tryReleaseShared(arg)) {// tryReleaseShared释放成功, 则释放双向链表中head的后继doReleaseShared();return true;}return false; }tryReleaseShared 方法 // Semaphore#tryReleaseShared protected final boolean tryReleaseShared(int releases) {for (;;) {// 获取当前的许可, 有并发问题int current getState();// 计算释放之后的许可数量int next current releases;if (next current) // overflowthrow new Error(Maximum permit count exceeded);// 自旋(通过CAS)设置状态. 设置成功则返回true.if (compareAndSetState(current, next))return true;} }doReleaseShared 方法 private void doReleaseShared() {for (;;) {// 记录当前headNode h head;// 队列中含有等待的节点if (h ! null h ! tail) {// 记录头节点等待状态int ws h.waitStatus;// 有下一个节点需要唤醒if (ws Node.SIGNAL) {// CAS 设置状态, 若没有成功, 则是并发导致失败.if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))continue;// 唤醒后继.unparkSuccessor(h);}// 并发情况下,可能会出现wa为0,需要状态为PROPAGATE,保证唤醒else if (ws 0 !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))continue;}if (h head)break;} }释放锁总结 Semaphore释放锁的过程总结为如下: 释放N个许可, 因为存在并发释放, 需要CAS确保设置更新后的值.唤醒双向链表中有效的等待节点. (可能存在并发问题,引入PROPAGATE状态)被唤醒的节点调用获取锁的流程. 图解Semaphore public static void main(String[] args) throws InterruptedException {Semaphore sem new Semaphore(2);for (int i 0; i 5; i) {Thread thread new Thread(() - {try {sem.acquire();TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();} finally {sem.release();}});thread.start();} }上面的程序, 通过添加不暂停断点输出日志信息来查看全部流程. 将输出拆分, 方便查看. 日志的第一部分: 节点中的数字代表线程标识, 为x表示没有记录线程. 最右边为抢到锁的节点, 里面记录的是线程号. 日志第二部分: 由于 线程0 和 线程1 开始释放锁, 并且都更新state的状态线程0 和 线程1 同时去唤醒队列中下一个有效节点, 存在并发问题线程0成功唤醒, 设置线程2的节点的waitStatus为0, 线程1去唤醒, 发现有人已经设置过, 所以设置线程2的节点的waitStatus为PROPAGATE(传播).线程0唤醒完毕,退出释放锁方法. 线程2抢锁成功, 并且线程1也随之退出释放锁的方法.线程2抢锁成功之后的图: 日志第三部分: 线程2唤醒线程3的节点, 线程2唤醒任务结束.线程3成功获取锁, 线程3去唤醒线程4. 线程3唤醒任务结束.日志第四部分: 线程4尝试获得锁, 最后失败.判断能否进入睡眠, 发现前任的waitStatus没有设置成SIGNAL, 因此不能睡眠, 再次尝试.尝试失败, 进入睡眠.日志第五部分: 线程2和线程3依次释放锁, 并且唤醒队列中下一个线程.线程2 唤醒 线程4, 线程4去抢锁, 线程2唤醒任务结束,退出释放锁方法.线程4尝试抢锁, 发现抢锁成功(后续还需要设置在队列中的状态等,所以并不是最终完成).线程3由于线程2修改了头节点, 因此线程3设置头节点状态为PROPAGATE.线程4和3唤醒任务结束.第五部分执行结束后: 线程4获取锁.头节点因此线程3和线程2并发唤醒队列中的线程,导致线程3第一次失败, 而第二次修改的时候,线程4已经将头节头改变, 但是碰巧列表中已经没有等待的节点,所以头节点的waitStatus为0, 因此线程3将头节点的waitStatus设置为PROPAGATE.线程4获取锁后, 会将封装线程4的节点中的线程置为null, 方便为GC回收. 日志第六层部分: 线程4释放锁, 进入doReleaseShared方法, 发现队列中已经没有节点. 因此AQS中最后的队列就下图所示: 结束语 了解Semaphore锁的释放和获取流程了解Semaphore的底层逻辑了解AQS底层的共享锁模式 创作不易,感谢大家观看, 如果有疑问和发现文中错误, 欢迎留言探讨! --------------------- 作者Wuv1Up 来源CSDN 原文https://blog.csdn.net/weixin_37150792/article/details/105692924 版权声明本文为作者原创文章转载请附上博文链接 内容解析ByCSDN,CNBLOG博客文章一键转载插件
http://www.pierceye.com/news/724494/

相关文章:

  • 特色专业网站建设模板北京网站建设公司分享网站改版注意事项
  • 网站上做地图手机上显示不出来的seo长尾快速排名
  • 网站怎么进行网络推广技术支持 湖州网站建设
  • 旅游找什么网站好仿朋友圈网站建设
  • 设置wordpress首页显示文章摘要aso优化是什么意思
  • 乡镇门户网站建设的现状及发展对策深圳网站建设评价
  • 河南省洛阳市建设银行的网站网站获得流量最好的方法是什么 ( )
  • 西安网站制作托wordpress媒体页
  • 杜集网站建设php网站怎么样
  • 山西做网站敬请期待哦
  • 前台网站开发技术Wordpress 建立学生档案
  • 邯郸网站制作找谁设置备份管理wordpress
  • 乌海学校网站建设镇江抖音seo
  • 网站建设在哪wordpress ping地址
  • 资讯文章网站模板徐州百度推广
  • 网站排名如何做西安有哪些网站设计公司
  • 广州网站开发学校wordpress优秀站点
  • wordpress 当前文章所属分类seo网站推广怎么做
  • 做网站要求电脑配置wordpress页眉描述
  • 做网站感想室内设计联盟邀请码怎么弄
  • 上海高端网站制作公司互联网黄页是什么
  • 网站服务器在阿里云专有网络做网站
  • 泰坦科技网站建设js代码 嵌入网站
  • 首都之窗门户网站首页中山做百度网站的公司吗
  • 网站 关键字 标签dede关闭网站
  • 甘肃路桥建设集团公司网站网页搭建模板
  • 山西省住房和城乡建设厅官网长沙seo关键词
  • 红酒 网站 模板网页qq登录保护在哪里
  • 目前哪些企业需要做网站建设的呢官方网站建设最重要的是
  • 电影题材网页设计欣赏长春seo关键词排名