什么是死锁?如何避免死锁?

409 阅读2分钟

什么是死锁?

死锁的四个条件。

1.互斥条件。共享资源X和Y只能被一个线程享用。

2.请求和保持条件。进程T1已经取得了共享资源X,在等待共享资源Y的时候,不释放共享资源X。

3.不可抢占条件。其他进程不能抢占当前进程T1的占有的资源。

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

为何会产生死锁

考虑具体问题,用户T1找柜员做个转账业务:账号A转账户B 100元,此时另一个用户T2也找柜员做一个转账业务:账户B转账户A 200元。于是T1和T2都去找账本,T1找到了账本A,等待账本B;T2找到了账本B,等待账本A。他们这样就会永远等待下去。这个就成为“死等”,在编程领域里成为死锁。

如何避免死锁?

1.破坏互斥条件,资源X和Y可以被多个线程共享。互斥有时不可行,因为加锁就是为了互斥。

2.破坏“请求和保持”条件,一次性申请所有的资源。 具体:“同时申请”这个操作是一个临界区。Java里可以使用Allocator类,同时申请资源apply()和同时释放资源free()。

3.破坏不可抢占条件,T1在申请资源的时候,如果申请不到,主动释放自己占有的资源。 具体:synchronized做不到。synchronized申请资源的时候,如果申请不到,线程直接进入阻塞状态,啥也干不了。可以通过Lock解决。

4.破坏循环等待条件,可以靠按序申请资源来预防。所有按序申请,是指资源是有序线性顺序的,申请的时候可以先申请资源序号小的,再申请资源序号大的,这样线性化后自然就不存在循环了。 具体:破坏循环等待条件,需要对资源进行排序,然后按序申请资源。我们假设每个账户都有不同的属性id,这个id可以作为排序字段,申请的时候,我们可以按照从小到大的顺序来申请。