I couldn't find a clear answer to this question, so apologies if this is nicely answered elsewhere.
Imagine I have something roughly like:
Class SomeClass
{
List<String> strings = new LinkedList<>();
public void updateList(List<String> newStrings) {
strings = newStrings;
}
public List<String> getMatchingStrings(String pattern) {
List<String> matches = new LinkedList<>();
for (String s : strings) {
if (matchesPattern(s, pattern)) { //Assume this just works
matches.add(s);
}
}
return matches;
}
}
Assuming another thread calls updateList(...) while some thread is calling getMatchingStrings(), will there be a "problem"?
The intended behavior is that the thread currently executing getMatchingStrings() will run on the old list, and a subsequent call will run on the updated list.
Any help is appreciated!
There is 'unsafe publication' in you code (no 'happens-before order' between write list field and read list field). Use blocked 'synchronized' or non-blocked 'volatile' or 'AtomicReference':
// with 'synchronized'
class SomeClass0 {
List<String> strings = new LinkedList<>();
public synchronized void updateList(List<String> newStrings) {
this.strings = newStrings;
}
public synchronized List<String> getMatchingStrings(String pattern) {
List<String> matches = new LinkedList<>();
for (String s : strings) {
if (matchesPattern(s, pattern)) { //Assume this just works
matches.add(s);
}
}
return matches;
}
}
// with 'volatile'
class SomeClass1 {
volatile List<String> strings = new LinkedList<>();
public void updateList(List<String> newStrings) {
this.strings = newStrings;
}
public List<String> getMatchingStrings(String pattern) {
List<String> localCopy = this.strings;
List<String> matches = new LinkedList<>();
for (String s : localCopy) {
if (matchesPattern(s, pattern)) { //Assume this just works
matches.add(s);
}
}
return matches;
}
}
// with 'AtomicReference'
class SomeClass2 {
AtomicReference<List<String>> strings =
new AtomicReference<>(new LinkedList<>());
public void updateList(List<String> newStrings) {
this.strings.set(newStrings);
}
public List<String> getMatchingStrings(String pattern) {
List<String> localCopy = this.strings.get();
List<String> matches = new LinkedList<>();
for (String s : localCopy) {
if (matchesPattern(s, pattern)) { //Assume this just works
matches.add(s);
}
}
return matches;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With