Skip to content

Commit 82534d9

Browse files
committed
synchronization
1 parent 63a5bc9 commit 82534d9

File tree

1 file changed

+82
-18
lines changed
  • Java/src/org/mlarocca/containers/trie/tst

1 file changed

+82
-18
lines changed

Java/src/org/mlarocca/containers/trie/tst/Tst.java

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,80 @@
44

55
import java.util.*;
66
import java.util.concurrent.atomic.AtomicBoolean;
7+
import java.util.concurrent.locks.ReentrantReadWriteLock;
78

89
public class Tst implements StringTree {
910

1011
private TstNode root;
1112

13+
/**
14+
* To make this container thread-safe, we need to synchronize all public methods.
15+
* Instead of using a generic reentrant lock through the synchronized keyword,
16+
* we define a Read/Write lock, so if we have more reads than writes, we can hold the lock
17+
* without blocking other reads. Only writes block all other operations.
18+
*/
19+
private ReentrantReadWriteLock.ReadLock readLock;
20+
private ReentrantReadWriteLock.WriteLock writeLock;
21+
1222
public Tst() {
1323
root = null;
24+
25+
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
26+
readLock = lock.readLock();
27+
writeLock = lock.writeLock();
1428
}
1529

1630
@Override
1731
public boolean add(String element) {
1832
if (element.isEmpty()) {
1933
throw new IllegalArgumentException("Keys must be non-empty");
2034
}
21-
if (root == null) {
22-
root = new TstNode(element);
23-
return true;
24-
} else {
25-
return root.add(element) != null;
35+
writeLock.lock();
36+
try {
37+
if (root == null) {
38+
root = new TstNode(element);
39+
return true;
40+
} else {
41+
return root.add(element) != null;
42+
}
43+
} finally {
44+
writeLock.unlock();
2645
}
2746
}
2847

2948
@Override
3049
public boolean remove(String element) {
31-
if (root == null) {
32-
return false;
33-
} else {
34-
return root.remove(element);
50+
writeLock.lock();
51+
try {
52+
if (root == null) {
53+
return false;
54+
} else {
55+
return root.remove(element);
56+
}
57+
} finally {
58+
writeLock.unlock();
3559
}
3660
}
3761

3862
@Override
3963
public void clear() {
40-
// Let the garbage collector do all the hard work
41-
root = null;
64+
writeLock.lock();
65+
try {
66+
// Let the garbage collector do all the hard work
67+
root = null;
68+
} finally {
69+
writeLock.unlock();
70+
}
4271
}
4372

4473
@Override
4574
public Optional<String> search(String element) {
46-
return root.search(element) == null ? Optional.empty() : Optional.of(element);
75+
writeLock.lock();
76+
try {
77+
return root.search(element) == null ? Optional.empty() : Optional.of(element);
78+
} finally {
79+
writeLock.unlock();
80+
}
4781
}
4882

4983
@Override
@@ -58,32 +92,62 @@ public Iterable<String> keysWithPrefix(String prefix) {
5892

5993
@Override
6094
public Iterable<String> keys() {
61-
return root == null ? new HashSet<>() : root.keys();
95+
readLock.lock();
96+
try {
97+
return root == null ? new HashSet<>() : root.keys();
98+
} finally {
99+
readLock.unlock();
100+
}
62101
}
63102

64103
@Override
65104
public Optional<String> min() {
66-
return Optional.ofNullable(root).map(TstNode::min);
105+
readLock.lock();
106+
try {
107+
return Optional.ofNullable(root).map(TstNode::min);
108+
} finally {
109+
readLock.unlock();
110+
}
67111
}
68112

69113
@Override
70114
public Optional<String> max() {
71-
return Optional.ofNullable(root).map(TstNode::max);
115+
readLock.lock();
116+
try {
117+
return Optional.ofNullable(root).map(TstNode::max);
118+
} finally {
119+
readLock.unlock();
120+
}
72121
}
73122

74123
@Override
75124
public boolean isEmpty() {
76-
return root == null || root.size() == 0;
125+
readLock.lock();
126+
try {
127+
return root == null || root.size() == 0;
128+
} finally {
129+
readLock.unlock();
130+
}
77131
}
78132

79133
@Override
80134
public int size() {
81-
return root == null ? 0 : root.size();
135+
readLock.lock();
136+
try {
137+
return root == null ? 0 : root.size();
138+
} finally {
139+
readLock.unlock();
140+
}
82141
}
83142

84143
@Override
85144
public int height() {
86-
return root == null ? 0 : root.height();
145+
readLock.lock();
146+
try {
147+
return root == null ? 0 : root.height();
148+
} finally {
149+
readLock.unlock();
150+
}
87151
}
88152

89153
private class TstNode {

0 commit comments

Comments
 (0)