JAVA中如何确保N个线程可以访问N个资源,但同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式:指定获取锁的顺序,并强制现场按照指定的顺序获取锁。因此,所有线程按照同样的顺序加锁和释放就不会出现死锁。
产生死锁的四个条件
-
互斥条件
一个资源每次只能被一个进程使用,互斥条件是非共享设备所必须的,不仅不能改变还需要加以保证。
-
请求和保持
一个进程因请求资源而阻塞且对已获得的资源保持不放
-
不可剥夺(不可抢占
线程已获得的资源在在未使用完之前,不能强行剥夺
-
循环等待
若干个线程之间形成一种头尾相接的循环等待资源关系
产生死锁的原因
- 竞争不可抢占性资源
- 竞争可消耗资源
- 线程推进顺序不当
预防死锁,预先破坏产生死锁的四个条件。互斥不可能破坏,所以有以下三种方法。
-
破坏请求和保持条件
解决方案有两种:
在线程开始之前一次性申请所有资源(必须等待所有请求的资源空闲时才能申请资源)
在线程开始时只申请运行初期所需的资源便开始运行运行过程中逐步释放自己已分配的且使用完毕的资源例如,一个线程要获取磁盘资源再通过打印机打印,那么初期获得磁盘资源即可,等待从磁盘中取出数据后便释放磁盘资源再申请打印机资源
-
破坏不可抢占条件
当一个已经保持了某些不可抢占资源的线程提出新的资源请求但不能满足时释放所有保持的资源。但是该方法实现起来比较复杂花费代价太大。
-
破坏循环等待条件
对系统中所有资源类型进行线性排列并赋予不同序号。每个线程必须按序号增序请求资源。这种方法对资源的利用率比前两种都高,但是前期要为设备指定序号,新设备加入会有一个问题,其次对用户编程也有限制。
线程必须等所有请求的资源都空闲时才能申请资源,
请问什么是死锁(deadlock)?
竞争不可抢占资源形成死锁
如果有两个线程T1和T2,要打开两个文件F1和F2,如果等线程T1打开F1和F2并释放后T2打开F1和F2不会出现任何问题。但是如果T1打开了F1此时需要去申请打开F2,此时T2打开了F2要去申请F1这样两个线程就阻塞了他们希望对方关闭自己所需的文件,但谁也无法运行,只能无限等待
竞争可消耗资源形成死锁
以生产者消费者为举例,有一个公共的空间S一个生产者线程PT一个消费者线程CT,如果CT线程先运行,并没有对有没有产品判断不断地像公共空间S申请自己所需要的资源,那么生产者线程就永远无法运行产生死锁
进程推进顺序不当造成死锁
于竞争不可抢占资源类似,但是进程推进顺序不当有可能可以成功运行