Java中的死锁

1.什么是死锁?

在理解什么是死锁之前先谈谈如何上锁的,

java中给某个对象上锁是使用synchronize这个关键字,而在java中的锁和其他语言的锁不同的地方在于synchronize是可重入的.

synchronize怎么上锁的?

1.修饰方法(普通方法,静态方法)

2.修饰代码块

但是synchronize本质上是对对象加锁,当使用修饰方法时,哪个对象调用了这个方法或者代码块,那么那个对象就会被上锁.

当两个线程对同一个对象加锁,此时会产生锁冲突,一个线程对该对象加上了锁另一个线程就得阻塞等待(并不是不能使用该线程或者对象)

当两个线程对不同对象加锁则不会产生锁冲突

当一个线程对该对象加锁,另一个线程对该对象不加锁也不会产生锁冲突

什么是可重入:

当一个线程对于一个对象上锁时候,对于这个锁再次上锁,如果此时不能够产生死锁则称之为可重入,如果产生了死锁则称为不可重入的,在Java中synchronize是可重入的.

具体的实现是:第一次加锁对象时会记录下此时这个锁是属于哪一个线程的,当再次加锁时会去检查一下这个锁是否属于同一个线程如果是则开放绿灯,否则阻塞等待.

初步了解死锁:

ok,现在我们可以谈谈什么是死锁了

假设有A和B打架,她两旗鼓相当最后将持续不下,互相拽着对方的头发,此时A对B说你松手我就放手,而B对A说你松手我就放手,但是说完谁也没有放手就一直保持这种状态.

死锁的情况大概分为三种情况(在我目前学习的知识下):

1.对于一个对象加锁两次

2.两个线程两把锁,各自都先有一把锁,但是要获取对方的锁.

3.多线程,多把锁(哲学家就餐问题)

现在有五位哲学家(cpu),桌子上有五根筷子(锁)和一只鸡(任务),哲学家只有思考(等待),和拿起筷子吃鸡(cpu执行任务)两种状态.当在极端情况下每个哲学家都拿起面前的筷子,而吃鸡需要两个筷子,每个哲学家都在等待其他哲学家放下筷子,此时就陷入了死锁.

通过上述案例,我想你应该对死锁有了大致的了解,我们再从死锁产生的几个条件中去深度剖析一下死锁.

2.死锁产生的条件:

1.互相使用:一个线程拿到锁之后,另一个线程就得等待

2.不可被强占:当线程1上锁之后,线程2不能抢占这个锁,只能等待线程1自己释放

3.请求和保持:当一个线程拿到一个锁A之后,还想要锁B,但是暂时拿不到锁B又不肯放弃手中拿到的锁A.

4.循环等待:线程1有一把锁A想要获取锁B,线程2拥有一把锁B想要锁A.线程1在等待线程2放弃锁B,线程2在等待线程1放弃锁A.此时陷入了一个循环链.

了解了死锁产生的条件之后我们就要去着手于如何解决死锁.而在Java中前三个条件是锁的特性,已经是成为了不可改变的条件,所以要想解决死锁问题我们就得从:"循环等待"这个突破口入手.

3.怎么去避免死锁?

现在由避免死锁的问题转换成如何去破坏循环等待这个条件,我们还是用"哲学家就餐"这个问题来举例.

还是五位哲学家,还是那只鸡,但是桌子上摆放的是五根有编号的筷子了,它们现在是有编制的的筷子了,这个时候为了人人都能吃上鸡,我们集体约定好摆在你面前左右的两根筷子中,你只能选择编号晓得筷子,如果编号晓得筷子被别人使用你就只能等待.此时我们的循环等待不攻自破.

所以在面临多把锁加锁的情况下我们提前约定好锁的顺序(从大到小,或者从小到大),这样就可以很好的避免死锁的问题.

至于更复杂的银行家算法在现实开发中不推荐使用,因为银行家算法很复杂,就算实现了银行家算法保不准其他地方会因为这个复杂的算法出问题,所以推荐使用简单有效的算法来避免死锁的问题.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值