
以下是转自:
死锁是由两个或多个线程持有的锁,等待其他线程处于死锁状态. 通常,当多个线程同时请求同一组锁但顺序不同时,就会发生死锁.
例如,如果线程1锁定A,然后尝试锁定B,而线程2锁定B,然后尝试锁定A,则会发生死锁. 线程1永远不会获得B,线程2永远不会获得A多线程死锁的例子,而且他们永远也不会知道发生了这种情况. 为了获得彼此的对象(A和B),它们将永远被阻挡. 这种情况是一个僵局.
情况如下:

Thread 1 locks A, waits for B Thread 2 locks B, waits for A
这是TreeNode类的示例,该类调用不同实例的同步方法:
public class TreeNode { TreeNode parent = null; List children = new ArrayList(); public synchronized void addChild(TreeNode child){ if(!this.children.contains(child)) { this.children.add(child); child.setParentOnly(this); } } public synchronized void addChildOnly(TreeNode child){ if(!this.children.contains(child){ this.children.add(child); } } public synchronized void setParent(TreeNode parent){ this.parent = parent; parent.addChildOnly(this); } public synchronized void setParentOnly(TreeNode parent){ this.parent = parent; } }
如果线程1调用parent.addChild(子方法),而另一个线程2调用child.setParent(父)方法,则两个线程中的父对象代表同一个对象,子线程也是如此. 将会发生死锁. 以下伪代码说明了此过程:

Thread 1: parent.addChild(child); //locks parent --> child.setParentOnly(parent); Thread 2: child.setParent(parent); //locks child --> parent.addChildOnly()
第一个线程1调用parent.addChild(子代). 由于addChild()是同步的,因此线程1锁定了父对象,以防止其他线程访问该对象.
然后线程2调用child.setParent(父级). 由于setParent()是同步的,因此线程2锁定了子对象,以防止其他线程访问该对象.
子对象和父对象现在被两个不同的线程锁定. 下一个线程1尝试调用child.setParentOnly()方法,但是由于子对象现在已被线程2锁定,因此该调用将被阻止. 线程2也会尝试调用parent.addChildOnly()多线程死锁的例子,但是由于父对象现在已被线程1锁定,因此线程2也被此方法阻塞. 现在,两个线程都被阻塞,并等待获取另一个线程持有的锁.

注意: 如上所述,这两个线程需要同时调用parent.addChild(child)和child.setParent(parent)方法,它们是相同的父对象和相同的子对象. 锁. 以上代码可能会在死锁发生之前运行一段时间.
这些线程需要同时获取锁. 例如,如果线程1稍稍领先于线程2,然后成功锁定了两个对象A和B,则在尝试锁定B时线程2将被阻塞,因此不会发生死锁. 由于线程调度通常是不可预测的,因此无法准确预测何时会发生死锁,而只能预测是否会发生死锁.
更复杂的僵局
该死锁可能包含两个以上的线程,这使检测死锁更加困难. 以下是4个线程中的死锁示例:

Thread 1 locks A, waits for B Thread 2 locks B, waits for C Thread 3 locks C, waits for D Thread 4 locks D, waits for A
线程1等待线程2,线程2等待线程3,线程3等待线程4,线程4等待线程1.
的死锁
更复杂的死锁方案发生在事务中. 事务可能包含多个SQL更新请求. 当在一个事务中更新一条记录时,该记录将被锁定以避免其他事务的更新请求,直到第一个事务结束. 同一事务中的每个更新请求都可以锁定一些记录.
当多个事务需要同时更新某些相同记录时,很可能发生死锁,例如:
Transaction 1, request 1, locks record 1 for update Transaction 2, request 1, locks record 2 for update Transaction 1, request 2, tries to lock record 2 for update. Transaction 2, request 2, tries to lock record 1 for update.
因为锁发生在不同的请求中,并且事务不可能事先知道它所需要的所有锁,所以很难检测并避免事务中的死锁.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-199881-1.html
可能是思维错了
面对美国在中东影响力不断下滑的趋势
专家说