Java中的死锁

文章介绍了死锁的概念,通过滑稽老铁和女生的饺子故事以及哲学家就餐问题生动解释了死锁的形成。死锁需满足四个条件:互斥使用、不可抢占、请求和保持、循环等待。破坏循环等待是防止死锁的一种方法,例如在哲学家问题中通过锁排序解决。
摘要由CSDN通过智能技术生成

1.什么是死锁

死锁:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期的阻塞,线程不可能正常终止。

举个栗子】滑稽老铁和女生去吃饺子。吃饺子需要醋和饺子。

滑稽老哥抄起了酱油瓶,女生抄起了醋瓶。

滑稽老铁:你先把醋瓶给我,我才把酱油瓶给你。

女生:你先把酱油瓶给我,我才能给你醋瓶。

如果两者彼此互不相让,就会导致死锁。

酱油和锁相当于两把锁,这两个人相当于两个线程。

【伪代码】

//线程1
synchronized(lock1) {
    sychronized(lock2) {
        //do something
    }
}

//线程2
synchronized(lock2) {
    sychronized(lock1) {
        //do something
    }
}

如果线程1拿到lock1后,线程2开始执行,拿到lock2,此时又开始执行线程1,但是线程1阻塞。线程2也会出现阻塞。

为了进一步阐述死锁的形成,我们引入“哲学家就餐问题”

  • 有个桌子,圈着一圈哲学家,桌子上放着足够的意大利面。每个哲学两两之间,放着一根筷子。

  •  每个哲学家只做两件事:思考人生 或者吃面条。思考人生的时候就会放下筷子。吃面条就会拿起左右两边的筷子
  • 如果哲学家发现筷子被占用,就会阻塞。
  • 假设每个哲学家,如果都同时拿起左手边的筷子,然后尝试拿起右手边的筷子,将会发现右手边的筷子都被占用了。但是由于哲学家互不相让,这是就会造成死锁的状态

2.如果避免死锁

死锁产生的四个必要条件:

  • 互斥使用,当一个锁被占用的时候,其他线程无法使用。
  • 不可抢占,资源请求者不能强制从资源占有者夺取资源,资源只能由资源占有者主动释放。
  • 请求和保持,即当资源请求者在请求其他支援的时候同时保持对原有资源的占有。
  • 循环等待,多个线程相互等待,造成死锁情况。

上述四个条件都成立的情况下,才能形成死锁的情况。当然,死锁的情况下如果打破上述任何一个条件,便可破解死锁。

2.1破坏循环等待

常用的一种死锁阻止技术就是锁排序

仍然是上面的哲学家问题:我们给每根筷子编一个序号,只有在获得大序号的筷子的情况下,才能获取小序号的筷子。

 

此时左上角的哲学家就会失去筷子,其他的哲学家就会获得两个筷子,使用完,并放下筷子。死锁情况也迎刃而解。

【伪代码】

//线程1和线程2约定好,先获取lock1,才能获取lock2

//线程1
synchronized(lock1){
    synchronized(lock2){
        //do something
    }
}

//线程2
synchronized(lock1){
    synchronized(lock2){
    //do something
    {
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值