import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; /** * Date: 14-3-2 */ public class TestDeadlock{ public static void main(String[] args){ Q q = new Q(); Config config = new Config(); config.setQ(q); config.setA(new A(config)); config.setB(new B(config)); config.getA().start(); config.getB().start(); } } class Config{ private A a; private B b; private Q q; public A getA() { return a; } public void setA(A a) { this.a = a; } public B getB() { return b; } public void setB(B b) { this.b = b; } public Q getQ() { return q; } public void setQ(Q q) { this.q = q; } } class B extends Thread{ private final byte[] lock = new byte[0]; private Q q ; private Config config; public B(Config config){ System.out.println("lockB="+lock); this.config = config; this.q = config.getQ(); } public void run(){ try{ int i = 0; while (true){ synchronized (lock){ if(!q.getQ().isEmpty()){ try { System.out.println("b waiting..."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //dead lock code i++; q.getQ().add("B" + i); System.out.println("thread B put B" + i); config.getA().notifyA(); //wait A lock,held B lock } TimeUnit.SECONDS.sleep(2); } }catch (Exception e){ e.printStackTrace(); } } public void notifyB(){ synchronized (lock){ System.out.println("A notify B..."); if(q.getQ().isEmpty()){ // synchronized (lock){ lock.notifyAll(); // } } } } } class A extends Thread{ private final byte[] lock = new byte[0]; private Q q ; private Config config; public A(Config config){ this.q = config.getQ(); this.config = config; } public void run(){ try{ while (true){ synchronized (lock){ if(q.getQ().isEmpty()){ try { System.out.println("a waiting..."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //dead lock code System.out.println("thread a get " + q.get()); if(q.getQ().isEmpty()){ config.getB().notifyB(); //wait B lock,held A lock } } TimeUnit.SECONDS.sleep(2); } }catch (Exception e){ e.printStackTrace(); } } public void notifyA(){ synchronized (lock){ System.out.println("B notify A..."); if(!this.q.getQ().isEmpty()){ // synchronized (lock){ lock.notifyAll(); // } } } } } class Q { private final BlockingQueue q = new LinkedBlockingQueue(); public void put(Object obj){ q.add(obj); } public Object get(){ return q.poll(); } public Queue getQ(){ return q; } }
不小心写了一段死锁代码,dump出来才知道。如注释处,跑了一下发现,A等B的锁,B却也在等A的锁,形成死锁。
典型的过度同步(effective java)。在同步块中调用外来逻辑容易导致异常、死锁、数据损坏。
以上把锁之外的逻辑移出synchronized块,或者改写notifyA/notifyB的逻辑即可。
相关推荐
通过对这段经典代码的分析,我们可以深刻理解到死锁是如何产生的以及如何避免死锁。在实际开发中,合理设计锁的使用方式,遵循一定的规范,可以有效减少死锁的发生,从而提高系统的稳定性和性能。
1. 互斥条件:即进程对所分配到的资源进行排他性使用,即在一段时间内某资源仅为一个进程所占有。此时,其他进程若申请该资源,则必须等待。 2. 请求与保持条件:一个进程因请求被占用的资源而发生阻塞时,对已获得...
`thinking`和`eating`函数分别模拟了这两个行为,通过`Sleep`函数使线程暂停一段时间来模拟实际的动作。`wait_to_eat`函数则用于获取并释放筷子,使用`EnterCriticalSection`和`LeaveCriticalSection`进行临界区的...
- **思考状态**:哲学家思考一段时间后进入饥饿状态。 - **饥饿状态**: - 尝试获取左侧的筷子,若成功,则尝试获取右侧的筷子。若均成功,则进入进食状态;否则返回思考状态。 - 如果左侧筷子不可用,则保持...
在Linux环境下,程序员在进行多线程或并发编程时经常会遇到死锁和段错误两种不同的问题,它们分别有着各自的概念、成因以及解决方法。 首先,死锁是指两个或两个以上的进程或线程在资源分配过程中,由于竞争资源而...
以下是一段SQL查询语句,用于找出所有未提交事务的详细信息: ```sql SELECT spid, blocked, waittime, waittype, waitresource, p.dbid, cpu, physical_io, memusage, open_tran, status, login_time, last_batch...
- **超时机制**: 如果一段时间内某个哲学家无法获得所需资源,则释放已持有的资源并重新尝试。 #### 四、程序实现 - **开发环境**: C#语言,使用.NET Framework或.NET Core框架。 - **用户界面**: 可以采用简单的...
标题:一个简单的和死锁有关的程序 ...综上所述,这段代码巧妙地展示了死锁的产生过程,帮助理解多线程编程中的资源竞争和同步问题。在实际开发中,应谨慎处理共享资源的访问,以避免死锁和其他并发问题。
1. 互斥条件:某些资源必须在一段时间内由一个进程独占。 2. 请求与保持条件:一个进程因请求被其他进程占用的资源而被阻塞,但同时又不释放自己已经占有的资源。 3. 不可剥夺条件:一旦资源被占有,除非占有者自愿...
根据提供的文件信息,我们可以推断出这段代码及描述主要关注的是如何在计算机系统中处理死锁问题,特别是针对进程间的资源分配与请求机制。接下来,将详细解释标题、描述、部分代码内容中所涉及的关键概念。 ### ...
互斥是指资源在一段时间内只能被一个进程使用;占有并等待指的是一个进程已经占有至少一个资源,但还请求其他资源;无剥夺意味着进程不能被强制剥夺已占有的资源,只能自行释放;循环等待则指存在一个进程链,每个...
- 死锁检测:InnoDB有内置的死锁检测机制,会在事务等待一段时间(可通过`innodb_lock_wait_timeout`参数设置)后进行检查。 - 死锁解决:一旦检测到死锁,InnoDB会选择一个事务作为牺牲品,回滚该事务的操作,以...
4. 设置锁的超时:通过`tryLock(long timeout, TimeUnit unit)`方法,让线程在等待一段时间后自动放弃锁。 5. 避免长时间持有锁:减少线程持有锁的时间,降低死锁的可能性。 总之,理解和掌握Java多线程中的死锁...
1. 互斥条件:资源在一段时间内只能由一个进程使用,即其他进程不能同时访问。 2. 请求与保持条件:进程已经保持至少一个资源,但又请求被其他进程占用的资源。 3. 不可剥夺条件:进程已获得的资源在未使用完之前不...
在计算机科学领域,死锁是多线程编程中一个重要的问题。当两个或多个进程相互等待对方释放...通过理解和分析这段代码,我们可以更好地理解如何在实际的多线程环境中预防和解决死锁问题,从而编写出更健壮的并发程序。
通过对这些信息的深入分析,管理员可以识别出导致死锁的模式或代码段,进而采取措施优化锁定策略、调整事务隔离级别或重新设计查询,以避免未来再次发生死锁。 ### 结论 SQL Server中的死锁分析是数据库性能管理和...
2. **源代码**:展示关键的代码段,如资源分配和安全性的检查。 3. **可视化展示**(可选):用图形界面显示资源申请过程,帮助理解。 4. **实验结果**:附带运行截图并解释结果。 5. **体会与疑问**:记录实验过程...
报告中包含了一段实验代码,以及实验的基本框架和实验过程。下面详细解释报告中的知识点: 1. Linux系统与C语言编程: Linux系统是基于Unix的一个开源操作系统,被广泛应用于服务器、桌面计算机以及嵌入式系统中。...