admin管理员组

文章数量:1357268

If in my class I have a field of type ImmutableMap like:

private ImmutableMap<String, State> states = ImmutableMap.of();

And there is 1 reader thread and 1 writer thread

Reader reads by calling methods like get on states with no synchronized or any kinds of barriers.

Writer thread writes by reassigning states to new variables like states = ImmutableMap.of(...) in a synchronized method (which, as far as I know, provides no guarantee of visibility in the other threads if they have no read memory barriers).

So the whole thing looks like this:

State read(String key) {
    return states.get(key);
}

synchronized void write(String key, State value) {
    var hashMap = new HashMap<String, State>();
    states.forEach(hashMap::put);
    hashMap.put(key, value);
    states = ImmutableMap.of(hashMap);
}

Is it true, that reader, when reading from a field states gets a valid value of states, that existed at one point of the time (linearizability is present)? Can reader thread read some nonsense when reading value of states due to compiler reordering?

If in my class I have a field of type ImmutableMap like:

private ImmutableMap<String, State> states = ImmutableMap.of();

And there is 1 reader thread and 1 writer thread

Reader reads by calling methods like get on states with no synchronized or any kinds of barriers.

Writer thread writes by reassigning states to new variables like states = ImmutableMap.of(...) in a synchronized method (which, as far as I know, provides no guarantee of visibility in the other threads if they have no read memory barriers).

So the whole thing looks like this:

State read(String key) {
    return states.get(key);
}

synchronized void write(String key, State value) {
    var hashMap = new HashMap<String, State>();
    states.forEach(hashMap::put);
    hashMap.put(key, value);
    states = ImmutableMap.of(hashMap);
}

Is it true, that reader, when reading from a field states gets a valid value of states, that existed at one point of the time (linearizability is present)? Can reader thread read some nonsense when reading value of states due to compiler reordering?

Share Improve this question edited Mar 27 at 22:18 blonded04 asked Mar 27 at 20:08 blonded04blonded04 5314 silver badges15 bronze badges 10
  • 1 It is unclear what you mean or what the problem is. Please edit your question to include a more detailed description of the problem you have. Also explain what you mean by "valid value" in this context. Specially, what an "invalid value" is in this context (and why it is). – Progman Commented Mar 27 at 21:47
  • 1 This question is similar to: Why is reference assignment atomic in Java?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – Iłya Bursov Commented Mar 27 at 22:15
  • 1 @IłyaBursov I'm asking about not atomicity (because afaik it's present always), but about visibility guarantees – blonded04 Commented Mar 27 at 22:17
  • 2 I think that the short answer is that read will always see a "valid" state snapshot, but that it could be stale. Nothing in the code (that you showed us) guarantees that the update to the state field in write will be visible in read. – Stephen C Commented Mar 27 at 23:49
  • 1 One solution is to declare state to be volatile. – Stephen C Commented Mar 27 at 23:59
 |  Show 5 more comments

1 Answer 1

Reset to default 2

Is it true, that reader, when reading from a field states gets a valid value of states, that existed at one point of the time (linearizability is present)? Can reader thread read some nonsense when reading value of states due to compiler reordering?

In your example each read of states has no happens-before ordering with writes to states.
According to the JMM that means every read is allowed to return any of the writes to states that happen anytime during the program execution.
This includes writes to states that happen later (in wall-clock time) in the same execution.
This also includes null - the default initialization value for states.

Here's the quote from the JLS:

Informally, a read r is allowed to see the result of a write w if there is no happens-before ordering to prevent that read.

To sum up:

  • linearizability isn't present
  • regarding "nonsense" I'd call it limited:
    • on the one hand, you don't get undefined behavior like in C\C++
    • on the other hand, the fact that a read is allowed to return any (including future) write to the variable - that alone causes huge amount of weird concurrency bugs in practice.

本文标签: javaAre operations to ImmutableCollection saved to nonfinal field threadsafeStack Overflow