Created
February 5, 2013 14:09
-
-
Save harrah/4714661 to your computer and use it in GitHub Desktop.
Demonstrates "Resource deadlock avoided" exception on a file lock when there is no deadlock.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io._ | |
object A | |
{ | |
/* | |
* Starts two concurrent threads that acquire file locks in a timed manner. | |
* Arguments: | |
* initialDelayA(ms) lockTimeA(ms) lockFileA initialDelayB(ms) lockTimeB(ms) lockFileB | |
* | |
* Example usage: demonstrates "Resource deadlock avoided" when there is no actual deadlock. | |
* Run this program concurrently: | |
* $ scala A 3000 5000 a 1000 7000 b | |
* $ scala A 1000 7000 a 3000 5000 b | |
* | |
* This will throw "IOException: Resource deadlock avoided" because the os doesn't have | |
* a deadlock detection granularity at the thread level, only at the process level. | |
* | |
* Time(s) A1 B1 a2 B2 | |
* 0 start start start start | |
* 1 lock b lock a | |
* 2 lock b lock a | |
* 3 wait on a lock b lock a wait on b | |
* ... | |
* | |
* The os sees process 1 acquire b and wait on a. It sees process 2 acquire a and wait on b. | |
* It thinks there is deadlock, which would be true if the processes were single threaded. | |
* There is no deadlock because the locks are in concurrent threads and not nested in a single thread. | |
* The os doesn't track the file locks at the thread level and doesn't know that, however. | |
* | |
* By reducing the lock times to be within the deadlock timeout of the os, the program completes successfully. | |
**/ | |
def main(args: Array[String]) { | |
run(args(0).toLong, args(1).toLong, args(2)) | |
run(args(3).toLong, args(4).toLong, args(5)) | |
} | |
/* Start a new thread that will: | |
* | |
* 1. wait `initialDelay` ms | |
* 2. Acquire a lock on `file` | |
* 3. wait `lockTime` ms | |
* 4. Release the lock on `file`. | |
*/ | |
def run(initialDelay: Long, lockTime: Long, file: String) { | |
val r = new Runnable { | |
def run { | |
println(s"Starting thread for $file") | |
Thread.sleep(initialDelay) | |
println(s"Initial wait complete for $file") | |
val fos = new FileOutputStream(new File(file)) | |
val lock = fos.getChannel.lock | |
println(s"Locked $file") | |
try { | |
Thread.sleep(lockTime) | |
println(s"Done waiting, $file") | |
} | |
finally { lock.release } | |
println(s"Released lock on $file") | |
} | |
} | |
new Thread(r).start() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Links thanks to @havocp: