b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

死锁原理和代码

电脑杂谈  发布时间:2020-07-09 04:18:08  来源:网络整理

多线程死锁的伪代码_c++ 线程死锁_c#线程死锁

死锁是由两个或多个线程持有的锁,等待其他线程处于死锁状态. 当多个线程同时以不同的顺序请求同一组锁时,通常会发生死锁.

例如,如果线程1锁定A,然后尝试锁定B,而线程2锁定B,然后尝试锁定A,则会发生死锁. 线程1永远不会获得B,线程2永远不会获得A,而且他们永远也不会知道发生了这种情况. 为了获得彼此的对象(A和B),它们将永远阻塞. 这种情况是一个僵局.

情况如下:

多线程死锁的伪代码_c#线程死锁_c++ 线程死锁

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(child)方法,而另一个线程2调用child.setParent(parent)方法,则两个线程中的父对象代表相同的对象,子对象也是如此. 将会发生死锁. 以下伪代码说明了此过程:

多线程死锁的伪代码_c++ 线程死锁_c#线程死锁

Thread 1: parent.addChild(child); //locks parent
          --> child.setParentOnly(parent);
Thread 2: child.setParent(parent); //locks child
          --> parent.addChildOnly()

第一个线程1调用parent.addChild(child). 由于addChild()是同步的,因此线程1锁定了父对象,以防止其他线程访问该对象.

然后线程2调用child.setParent(parent). 由于setParent()是同步的,因此线程2锁定了子对象,以防止其他线程访问该对象.

子对象和父对象现在被两个不同的线程锁定. 下一个线程1尝试调用child.setParentOnly()方法,但是由于子对象现在已被线程2锁定,因此该调用将被阻止. 线程2还尝试调用parent.addChildOnly(),但是由于父对象现在已被线程1锁定,因此线程2也被此方法阻塞. 现在,两个线程都被阻塞,并等待获取另一个线程持有的锁.

多线程死锁的伪代码_c++ 线程死锁_c#线程死锁

注意: 如上所述,这两个线程需要同时调用parent.addChild(child)和child.setParent(parent)方法,以及相同的父对象和相同的子对象,因此可以死锁. 以上代码可能会在死锁发生之前运行一段时间.

这些线程需要同时获取锁. 例如,如果线程1稍稍领先于线程2,然后成功锁定了两个对象A和B,那么在尝试锁定B时线程2将被阻塞,因此不会发生死锁. 由于线程调度通常是不可预测的,因此无法准确预测何时会发生死锁,而只是可能会发生死锁.

更复杂的僵局

该死锁可能包含两个以上的线程,这使检测死锁更加困难. 以下是4个线程死锁的示例:

c#线程死锁_c++ 线程死锁_多线程死锁的伪代码

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-273696-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 宋景公
        宋景公

        但绝不容忍侵犯主权

      每日福利
      热点图片
      拼命载入中...