-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathno_deadlock.java
More file actions
63 lines (55 loc) · 1.74 KB
/
Copy pathno_deadlock.java
File metadata and controls
63 lines (55 loc) · 1.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class MyLock {
private LockManager lockManager;
private Lock lock = new Lock();
public MyLock(LockManager lockManager) {
this.lockManager = lockManager;
}
public void lock() throws Exception {
Thread thread = getThisThread();
lockManager.lock(lock, thread);
}
public void unlock() {
Thread thread = getThisThread();
lockManager.unlock(lock, thread);
}
}
class LockManager {
synchronized HashMap<Lock, Thread> lockToThread;
synchronized HashMap<Thread, Lock> threadToWaitingLock;
private synchronized boolean wouldDeadlock(Lock lock, Thread thread) {
// If lock unused then allow the lock.
if(!lockToThread.hasKey(lock))
return false;
// Lock is used so check for deadlock.
Thread initThread = thread;
// This must end because it cannot contain cycles since that is what we are detecting and
// forbidding here in the first place.
while(true) {
thread = lockToThread.get(lock);
if(thread.equals(initThread))
return true; // we looped lock-dependencies so deadlock
if(!threadToWaitingLock.hasKey(thread))
return false; // this breaks the lock-list so no deadlock
lock = threadToWaitingLock.get(thread);
}
assert false; // impossible
return true;
}
private void allowLock(Lock lock, Thread thread) {
lockToThread.put(lock, thread);
threadToWaitingLock.put(thread, lock);
}
public void lock(Lock lock, Thread thread) throws Exception {
synchronized(this) {
if(wouldDeadlock(lock, thread))
throw new Exception("Deadlock");
allowLock(lock, thread);
}
lock.lock();
threadToWaitingLock.remove(thread); // synchronized(this) may be better than synchronized treadToWaitingLock...?
}
public void unlock(Lock lock, Thread thread) {
lock.unlock();
lockToThread.remove(lock);
}
}