96SEO 2026-02-20 02:49 0
锁其实就是一种同步机制一个线程拥有对一块资源的锁那么该线程对这块资源的处理是与其他线程互斥的在该线程未释放锁之前其它线程会被限制对统一资源的访问。

有了对锁概念的认知我们再来看下死锁是什么所谓死锁其实就是指在多线程或者多进程运行状态下因争夺资源而导致的一种互不让步的僵局导致各自均进入阻塞状态如果没有外力强制中断或者程序设置超时中断的推动则程序将一直处于僵持崩溃状态。
资源互斥资源互斥就是上面我们说的锁线程持有的锁是需要具备独占且排他使用的不可被剥夺线程在对持有的资源未使用完毕前是不会被其他线程强行剥夺的请求并保持线程在请求获取新的资源时当前所持有的资源依旧继续占用循环等待多个线程对于获取锁行为是一个环形例如线程A持有锁1需要获取锁2才能进行后续操作线程B持有锁2需要获取锁1才能进行后续操作此时就形成了环
com.markus.onjava.concurrent;/***
lockA));thread1.start();thread2.start();}
]);Thread.sleep(2000);synchronized
我们可以通过jstack来查看进程中的线程状态来分析是哪些线程出现了死锁状态
[0x000000030a74d000]java.lang.Thread.State:
com.markus.onjava.concurrent.Task.run(DeadLockDemo.java:38)-
java.lang.Thread.run(Thread.java:748)Thread-0
[0x000000030a64a000]java.lang.Thread.State:
com.markus.onjava.concurrent.Task.run(DeadLockDemo.java:38)-
java.lang.Thread.run(Thread.java:748)#
com.markus.onjava.concurrent.Task.run(DeadLockDemo.java:38)-
java.lang.Thread.run(Thread.java:748)
com.markus.onjava.concurrent.Task.run(DeadLockDemo.java:38)-
java.lang.Thread.run(Thread.java:748)Found
上面介绍了产生死锁的必要条件所谓必要条件就是要都满足才能产生死锁所以在预防的时候我们可以任意打破死锁的4个必要条件来预防死锁但又因为资源互斥是底层操作系统的固有特性应用层面是无法改变的所以我们可以通过破坏剩余的三个条件来进行预防
一个餐桌上有五名哲学家以及五根筷子这五根筷子分别插入到五位哲学家的间隔处哲学家想要饮食则必须同时拿起左右手两边的筷子所以现在就有问题了如果有人能够吃饭那肯定会有人等待在某种情况下还极可能造成所有人都在等待以导致死锁的情况。
com.markus.onjava.concurrent.deadlock;import
java.util.concurrent.ArrayBlockingQueue;
java.util.concurrent.BlockingQueue;/***
利用阻塞队列实现当前筷子同一时刻只能被一个人持有其他人想要获取这跟筷子则必须等待private
com.markus.onjava.concurrent.deadlock;import
java.util.concurrent.TimeUnit;/***
拿起左手边的筷子left.pickUp();System.out.println(this
com.markus.onjava.concurrent.deadlock;import
java.util.concurrent.CompletableFuture;/***
StickHolder[n];Arrays.setAll(sticks,
通过模数n选择右手边的筷子并将最后一个哲学家指向第一位哲学家旁边整体形成一个环Arrays.setAll(philosophers,
Arrays.stream(philosophers).forEach(CompletableFuture::runAsync);}public
主流程等待100s后再退出此时我们可以观察哲学家的用餐场景new
}执行晚餐现场的代码后我们可以发现起初还能正常的执行但一会就会形成互相等待的场景这种等待形成了一个环也就造成了死锁。
mode):ForkJoinPool.commonPool-worker-5
[0x000000030668e000]java.lang.Thread.State:
java.util.concurrent.ForkJoinPool)at
java.util.concurrent.ForkJoinPool.awaitWork(ForkJoinPool.java:1824)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1693)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)ForkJoinPool.commonPool-worker-7
[0x000000030658b000]java.lang.Thread.State:
java.util.concurrent.ForkJoinPool)at
java.util.concurrent.ForkJoinPool.awaitWork(ForkJoinPool.java:1824)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1693)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)ForkJoinPool.commonPool-worker-6
[0x0000000306488000]java.lang.Thread.State:
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)at
com.markus.onjava.concurrent.deadlock.StickHolder.pickUp(StickHolder.java:30)at
com.markus.onjava.concurrent.deadlock.Philosopher.run(Philosopher.java:31)at
java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)at
java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)at
java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1618)at
java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)at
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)at
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)ForkJoinPool.commonPool-worker-4
[0x0000000306385000]java.lang.Thread.State:
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)at
com.markus.onjava.concurrent.deadlock.StickHolder.pickUp(StickHolder.java:30)at
com.markus.onjava.concurrent.deadlock.Philosopher.run(Philosopher.java:31)at
java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)at
java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)at
java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1618)at
java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)at
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)at
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)ForkJoinPool.commonPool-worker-3
[0x0000000306282000]java.lang.Thread.State:
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)at
com.markus.onjava.concurrent.deadlock.StickHolder.pickUp(StickHolder.java:30)at
com.markus.onjava.concurrent.deadlock.Philosopher.run(Philosopher.java:31)at
java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)at
java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)at
java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1618)at
java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)at
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)at
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)ForkJoinPool.commonPool-worker-2
[0x000000030617f000]java.lang.Thread.State:
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)at
com.markus.onjava.concurrent.deadlock.StickHolder.pickUp(StickHolder.java:30)at
com.markus.onjava.concurrent.deadlock.Philosopher.run(Philosopher.java:31)at
java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)at
java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)at
java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1618)at
java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)at
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)at
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)ForkJoinPool.commonPool-worker-1
[0x000000030607c000]java.lang.Thread.State:
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)at
com.markus.onjava.concurrent.deadlock.StickHolder.pickUp(StickHolder.java:30)at
com.markus.onjava.concurrent.deadlock.Philosopher.run(Philosopher.java:31)at
java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)at
java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)at
java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1618)at
java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)at
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)at
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)at
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)at
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
通过对上面基础知识的学习我们可以知道代码产生死锁的原因有以下几点
一根筷子资源同一时刻只能被一位哲学家使用也就是资源互斥哲学家每人都持有一根筷子并且均尝试去获取另一根筷子就是请求并保持哲学家持有的筷子不能被强制回收只能由自己完成任务主动释放也就是不可被剥夺哲学家的等待形成了一个环造成循环等待
前面我们说了资源互斥是系统特性我们先忽略打破这个条件下面我们来通过其他三个条件来实现预防死锁的解决方案
打破循环等待-我们可以看到哲学家都是尝试先拿起右边的筷子再拿起右边的筷子这样就互相之间就形成了环我们可以指定某一位哲学家不按照这样的顺序取筷子则形成不了环也就不会造成情况了。
com.markus.onjava.concurrent.deadlock;import
java.util.concurrent.CompletableFuture;/***
StickHolder[n];Arrays.setAll(sticks,
Philosopher[n];Arrays.setAll(philosophers,
通过将第2位哲学家颠倒拿放筷子的顺序来修正死锁Arrays.stream(philosophers).forEach(CompletableFuture::runAsync);}public
}打破循环条件还有另一种方案就是调大资源数超出你的机器的CPU物理核数这样就导致同一时刻肯定会有一位哲学家不参与活动的进行这也就形成不了循环等待的情况我们还可以通过打破请求并保持的条件
}不可被剥夺条件实现起来比较麻烦核心思想就是如果拿不到就去旁边手中抢过来。
综上预防死锁的方式可以通过打破那四个必要条件的其中一个即可其中打破循环等待条件又是最容易的我们通常会通过这种思路进行预防。
上述就是对死锁的简单介绍包括死锁是什么什么情况下会导致死锁四个必要条件以及如何预防死锁打破四个必要条件之一即可我们也可以看出在Java语言层面上是无法支持我们来避免死锁的所以我们只能通过谨慎的设计来避免这个问题。
避免并发问题最简单有效的方法就是永远不要共享资源但这看来也是不现实的所以在设计的时候我们也可以通过画布画出资源的依赖关系来谨慎设计方案等等其他方法来避免系统出现死锁。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback