多线程死锁问题
2017-07-26 12:18
148 查看
一、死锁的概念
多线程以及多进程改善了系统资源的利用率并提高了系统 的处理能力。然而,并发执行也带来了新的问题——死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
下面我们通过一些实例来说明死锁现象。
先看生活中的一个实例,2个人一起吃饭但是只有一双筷子,2人轮流吃(同时拥有2只筷子才能吃)。某一个时候,一个拿了左筷子,一人拿了右筷子,2个人都同时占用一个资源,等待另一个资源,这个时候甲在等待乙吃完并释放它占有的筷子,同理,乙也在等待甲吃完并释放它占有的筷子,这样就陷入了一个死循环,谁也无法继续吃饭。。。
在计算机系统中也存在类似的情况。例如,某计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态
二、产生死锁的条件
(1)互斥条件。即某个资源在一段时间内只能由一个进程或者线程占有,不能同时被两个或者两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等,必须在占有该资源的进程或者线程主动释放它之后,其他进程或者线程才能只有该资源。这是由资源本身属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。
(2)不可抢占条件。进程或线程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
(3)占有且申请条件。进程或线程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程或者线程所占有,此时该进程或者线程会被阻塞;但是,它在等待新资源之时,仍继续占有已占有的资源。
(4)循环等待条件。存在一个进程或线程等待序列{P1,P2,....,P3},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一资源,.......,而Pn又等待P1所占有的资源,形成一个循环等待环。
PS:上面所提到的四个条件在死锁发生时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。
三、出现死锁的五种场景
(1)notify与notifyAll的使用。
如:
两个生产者P1、P2,两个消费者C1、C2,共同操作一个队列,队列最大长度为1。
开始P1、P2、C1、C2都处于运行状态(RUNNABLE)。
C1先获得锁,P1、P2、C2为BLOCKED状态。C1发现队列为空,主动进入WAITING。C2接着获得锁,成为RUNNABLE状态,发现队列为空,主动进入WAITING。
P1接着获得锁,成为RUNNABLE状态,在队列中插入一个元素,notify到了另一个生产者P2。P1循环生产,发现队列不为空,成为WAITING。
P2成为RUNNABLE状态,发现队列有值,主动进入WAITING。
此时锁已被释放,但P1、P2、C1、C2都处于WAITING状态,没有线程去获取锁,死了。
(2)同一个线程拥有有多把锁
如:
(3)使用循环
如:
thread1首先执行,加锁,while(!condition)为永真持续循环,此时thread2等待thread1解锁从而获取锁,thread1等待thread2将condition置为true,跳出循环解锁,这就构成了死锁。
(4)thread.suspend()和thread.stop()
当挂起或者停止一个拥有某一把锁的线程时,该线程并不会释放锁,这就容易造成死锁。
(5)哲学家就餐问题
5个哲学家,5跟筷子,哲学家必须用两只筷子吃东西,若5个人同时拿起自己左边(右边)的筷子会将构成死锁。
多线程以及多进程改善了系统资源的利用率并提高了系统 的处理能力。然而,并发执行也带来了新的问题——死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
下面我们通过一些实例来说明死锁现象。
先看生活中的一个实例,2个人一起吃饭但是只有一双筷子,2人轮流吃(同时拥有2只筷子才能吃)。某一个时候,一个拿了左筷子,一人拿了右筷子,2个人都同时占用一个资源,等待另一个资源,这个时候甲在等待乙吃完并释放它占有的筷子,同理,乙也在等待甲吃完并释放它占有的筷子,这样就陷入了一个死循环,谁也无法继续吃饭。。。
在计算机系统中也存在类似的情况。例如,某计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态
二、产生死锁的条件
(1)互斥条件。即某个资源在一段时间内只能由一个进程或者线程占有,不能同时被两个或者两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等,必须在占有该资源的进程或者线程主动释放它之后,其他进程或者线程才能只有该资源。这是由资源本身属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。
(2)不可抢占条件。进程或线程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
(3)占有且申请条件。进程或线程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程或者线程所占有,此时该进程或者线程会被阻塞;但是,它在等待新资源之时,仍继续占有已占有的资源。
(4)循环等待条件。存在一个进程或线程等待序列{P1,P2,....,P3},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一资源,.......,而Pn又等待P1所占有的资源,形成一个循环等待环。
PS:上面所提到的四个条件在死锁发生时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。
三、出现死锁的五种场景
(1)notify与notifyAll的使用。
如:
两个生产者P1、P2,两个消费者C1、C2,共同操作一个队列,队列最大长度为1。
开始P1、P2、C1、C2都处于运行状态(RUNNABLE)。
C1先获得锁,P1、P2、C2为BLOCKED状态。C1发现队列为空,主动进入WAITING。C2接着获得锁,成为RUNNABLE状态,发现队列为空,主动进入WAITING。
P1接着获得锁,成为RUNNABLE状态,在队列中插入一个元素,notify到了另一个生产者P2。P1循环生产,发现队列不为空,成为WAITING。
P2成为RUNNABLE状态,发现队列有值,主动进入WAITING。
此时锁已被释放,但P1、P2、C1、C2都处于WAITING状态,没有线程去获取锁,死了。
(2)同一个线程拥有有多把锁
如:
(3)使用循环
如:
thread1首先执行,加锁,while(!condition)为永真持续循环,此时thread2等待thread1解锁从而获取锁,thread1等待thread2将condition置为true,跳出循环解锁,这就构成了死锁。
(4)thread.suspend()和thread.stop()
当挂起或者停止一个拥有某一把锁的线程时,该线程并不会释放锁,这就容易造成死锁。
(5)哲学家就餐问题
5个哲学家,5跟筷子,哲学家必须用两只筷子吃东西,若5个人同时拿起自己左边(右边)的筷子会将构成死锁。
相关文章推荐
- java多线程(八)-死锁问题和java多线程总结
- 多线程死锁问题
- J2SE学习笔记:多线程、单例模式延迟加载懒汉式同步、死锁问题
- java语言基础(93)——多线程中的死锁问题
- 多线程问题--- 死锁
- 19-多线程(验证同步函数的锁) 21-多线程(单例模式涉及的多线程问题) 1 2 22-多线程(死锁示例) 23-Objcet放的位置产生的问题
- 黑马程序员 多线程死锁的问题.
- 【JAVA多线程问题之死锁】
- 多线程死锁问题
- JAVA基础 day11 多线程 同步代码块 死锁问题
- Java多线程死锁问题测试
- 多线程(五)——多线程安问题之死锁(Dead Lock )
- [置顶] 多线程编程之线程死锁问题
- 多线程死锁问题
- 多线程死锁问题(this锁和普通锁区别)
- java 生产者消费者问题-多线程与死锁
- java学习日记(6)____多线程的安全问题与死锁的产生
- 一个多线程死锁案例,如何避免及解决死锁问题?
- 多线程中的线程通信以及死锁问题
- 一个多线程死锁的问题,一个循环引用的问题