-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDeadlockConditionFixed.java
More file actions
112 lines (103 loc) · 4.13 KB
/
DeadlockConditionFixed.java
File metadata and controls
112 lines (103 loc) · 4.13 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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* DeadlockConditionFixed.java
*
* Written by Andrew Lui, The Open University of Hong Kong 2020
*
* About: This program aims to demonstrate deadlock can occur when semaphores (or mutex locks) are misued.
This program uses the semaphore lock methods in Java to implement the critical section situation, but uses two locks without observing the rules of total ordering
and sometimes result in deadlock
Instruction: (1) Observe the order of acquiring the locks is always in the same order. (2) Execute the program.
(3) No error should occur
*
*/
public class DeadlockConditionFixed {
private static int value = 0;
private static Thread threadA;
private static Thread threadB;
private static Lock lockA, lockB;
private static final int LOOP_COUNT = 100000;
static long updatedTime = System.currentTimeMillis(); // a variable recording the last update of the variable value
static class TestProcessA implements Runnable {
public void run() {
try {
for (int i = 0; i < LOOP_COUNT; i++) {
lockA.lock(); // Acquire Lock A and then Lock B
lockB.lock();
value = value + 1;
updatedTime = System.currentTimeMillis();
lockB.unlock(); // the release should always be in FILO order
lockA.unlock();
}
} catch (Exception ex) {
System.err.println("The thread is interrupted due to error");
} finally {
}
}
}
static class TestProcessB implements Runnable {
public void run() {
try {
for (int i = 0; i < LOOP_COUNT; i++) {
lockA.lock();
lockB.lock(); // Acquire Lock A and then Lock B, the same order
value = value - 1;
updatedTime = System.currentTimeMillis();
lockB.unlock();
lockA.unlock(); // the release should always be in FILO order
}
} catch (Exception ex) {
System.err.println("The thread is interrupted due to error");
} finally {
}
}
}
static class MonitorProcess implements Runnable {
long prevTime;
public void run() {
try {
while (true) {
if (!threadA.isAlive() && !threadB.isAlive()) {
break;
}
Thread.sleep(5);
if (prevTime == updatedTime) {
if (value != 0) {
System.out.println("ERROR: Looks like deadlock has happened. The current value is " + value);
break;
} else {
System.out.println("Finishing ...");
}
}
prevTime = updatedTime;
}
} catch (Exception ex) {
System.err.println("The thread is interrupted due to error");
} finally {
}
}
}
public static void main(String args[]) throws Exception {
long startTime = System.currentTimeMillis();
value = 0;
lockA = new ReentrantLock();
lockB = new ReentrantLock();
threadA = new Thread(new TestProcessA());
threadB = new Thread(new TestProcessB());
Thread monitorThread = new Thread(new MonitorProcess());
threadA.start();
threadB.start();
monitorThread.start();
threadA.join();
threadB.join();
if (value != 0) {
System.out.println("Error found due to race condition: value is " + value + " (should be 0)");
} else {
System.out.println("The threads have finished and no deadlock occured");
}
long endTime = System.currentTimeMillis();
long timeTaken = (endTime - startTime);
System.out.println("Time taken = " + timeTaken + " ms");
}
}