05 死锁

作者: random123 | 来源:发表于2020-05-22 22:10 被阅读0次

    相对于上一节中使用XXX.class粗粒度的锁,可以使用细粒度锁提升性能。

    首先转账业务的资源:转出账户,转入账户。需要分别对两个账户加锁。

    加锁示意图

    细粒度锁提升了性能,但是存在死锁问题:比如A、B两个账户,线程1从A向B转账,线程2从B向A转账,线程1获得A的锁,等待B锁;线程2获得B锁,等待A锁,陷入死锁。

    出现死锁满足的四个条件:

    1.互斥,共享资源 X 和 Y 只能被一个线程占用;

    2.占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;

    3.不可抢占,其他线程不能强行抢占线程 T1 占有的资源;

    4.循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。

    解决死锁的方式:

    1.破坏互斥性。使用锁的目的是为了互斥,无法破坏。

    2.破坏占有并等待:一次性申请所有的资源。这个例子里,线程所使用的资源是转出账户和转入账户。一次性获取两者的资源。引入一个管理单例对象,负责分配和收回资源。

    3.破坏不可抢占条件:java中的synchronized并不能破坏这一条,无法自己释放锁。但是Lock类是可以的

    4.。破坏循环等待:给资源排好顺序,按顺序分配资源。

    本节问题:破坏占用且等待条件,我们也是锁了所有的账户,而且还是用了死循环 while(!actr.apply(this, target));这个方法,那它比 synchronized(Account.class) 有没有性能优势呢?

    问题回答:synchronized(Account.class)锁住的是所有对象,导致只能串行进行;使用单例管理的方式,只锁住操作中涉及的对象,对其他对象没有影响。

    相关文章

      网友评论

          本文标题:05 死锁

          本文链接:https://www.haomeiwen.com/subject/guocahtx.html