提交 38d28976 编写于 作者: S shade

8145539: (coll) AbstractMap.keySet and .values should not be volatile

Reviewed-by: redestad, plevart, dl, psandoz
上级 ad3b3f10
...@@ -304,9 +304,28 @@ public abstract class AbstractMap<K,V> implements Map<K,V> { ...@@ -304,9 +304,28 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
* Each of these fields are initialized to contain an instance of the * Each of these fields are initialized to contain an instance of the
* appropriate view the first time this view is requested. The views are * appropriate view the first time this view is requested. The views are
* stateless, so there's no reason to create more than one of each. * stateless, so there's no reason to create more than one of each.
*
* <p>Since there is no synchronization performed while accessing these fields,
* it is expected that java.util.Map view classes using these fields have
* no non-final fields (or any fields at all except for outer-this). Adhering
* to this rule would make the races on these fields benign.
*
* <p>It is also imperative that implementations read the field only once,
* as in:
*
* <pre> {@code
* public Set<K> keySet() {
* Set<K> ks = keySet; // single racy read
* if (ks == null) {
* ks = new KeySet();
* keySet = ks;
* }
* return ks;
* }
*}</pre>
*/ */
transient volatile Set<K> keySet; transient Set<K> keySet;
transient volatile Collection<V> values; transient Collection<V> values;
/** /**
* {@inheritDoc} * {@inheritDoc}
...@@ -325,8 +344,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> { ...@@ -325,8 +344,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
* method will not all return the same set. * method will not all return the same set.
*/ */
public Set<K> keySet() { public Set<K> keySet() {
if (keySet == null) { Set<K> ks = keySet;
keySet = new AbstractSet<K>() { if (ks == null) {
ks = new AbstractSet<K>() {
public Iterator<K> iterator() { public Iterator<K> iterator() {
return new Iterator<K>() { return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator(); private Iterator<Entry<K,V>> i = entrySet().iterator();
...@@ -361,8 +381,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> { ...@@ -361,8 +381,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
return AbstractMap.this.containsKey(k); return AbstractMap.this.containsKey(k);
} }
}; };
keySet = ks;
} }
return keySet; return ks;
} }
/** /**
...@@ -382,8 +403,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> { ...@@ -382,8 +403,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
* method will not all return the same collection. * method will not all return the same collection.
*/ */
public Collection<V> values() { public Collection<V> values() {
if (values == null) { Collection<V> vals = values;
values = new AbstractCollection<V>() { if (vals == null) {
vals = new AbstractCollection<V>() {
public Iterator<V> iterator() { public Iterator<V> iterator() {
return new Iterator<V>() { return new Iterator<V>() {
private Iterator<Entry<K,V>> i = entrySet().iterator(); private Iterator<Entry<K,V>> i = entrySet().iterator();
...@@ -418,8 +440,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> { ...@@ -418,8 +440,9 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
return AbstractMap.this.containsValue(v); return AbstractMap.this.containsValue(v);
} }
}; };
values = vals;
} }
return values; return vals;
} }
public abstract Set<Entry<K,V>> entrySet(); public abstract Set<Entry<K,V>> entrySet();
......
...@@ -380,10 +380,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> ...@@ -380,10 +380,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
*/ */
public Set<K> keySet() { public Set<K> keySet() {
Set<K> ks = keySet; Set<K> ks = keySet;
if (ks != null) if (ks == null) {
return ks; ks = new KeySet();
else keySet = ks;
return keySet = new KeySet(); }
return ks;
} }
private class KeySet extends AbstractSet<K> { private class KeySet extends AbstractSet<K> {
...@@ -418,10 +419,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> ...@@ -418,10 +419,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
*/ */
public Collection<V> values() { public Collection<V> values() {
Collection<V> vs = values; Collection<V> vs = values;
if (vs != null) if (vs == null) {
return vs; vs = new Values();
else values = vs;
return values = new Values(); }
return vs;
} }
private class Values extends AbstractCollection<V> { private class Values extends AbstractCollection<V> {
......
...@@ -902,8 +902,12 @@ public class HashMap<K,V> extends AbstractMap<K,V> ...@@ -902,8 +902,12 @@ public class HashMap<K,V> extends AbstractMap<K,V>
* @return a set view of the keys contained in this map * @return a set view of the keys contained in this map
*/ */
public Set<K> keySet() { public Set<K> keySet() {
Set<K> ks; Set<K> ks = keySet;
return (ks = keySet) == null ? (keySet = new KeySet()) : ks; if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
} }
final class KeySet extends AbstractSet<K> { final class KeySet extends AbstractSet<K> {
...@@ -949,8 +953,12 @@ public class HashMap<K,V> extends AbstractMap<K,V> ...@@ -949,8 +953,12 @@ public class HashMap<K,V> extends AbstractMap<K,V>
* @return a view of the values contained in this map * @return a view of the values contained in this map
*/ */
public Collection<V> values() { public Collection<V> values() {
Collection<V> vs; Collection<V> vs = values;
return (vs = values) == null ? (values = new Values()) : vs; if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
} }
final class Values extends AbstractCollection<V> { final class Values extends AbstractCollection<V> {
......
...@@ -964,10 +964,11 @@ public class IdentityHashMap<K,V> ...@@ -964,10 +964,11 @@ public class IdentityHashMap<K,V>
*/ */
public Set<K> keySet() { public Set<K> keySet() {
Set<K> ks = keySet; Set<K> ks = keySet;
if (ks != null) if (ks == null) {
return ks; ks = new KeySet();
else keySet = ks;
return keySet = new KeySet(); }
return ks;
} }
private class KeySet extends AbstractSet<K> { private class KeySet extends AbstractSet<K> {
...@@ -1069,10 +1070,11 @@ public class IdentityHashMap<K,V> ...@@ -1069,10 +1070,11 @@ public class IdentityHashMap<K,V>
*/ */
public Collection<V> values() { public Collection<V> values() {
Collection<V> vs = values; Collection<V> vs = values;
if (vs != null) if (vs == null) {
return vs; vs = new Values();
else values = vs;
return values = new Values(); }
return vs;
} }
private class Values extends AbstractCollection<V> { private class Values extends AbstractCollection<V> {
......
...@@ -528,8 +528,12 @@ public class LinkedHashMap<K,V> ...@@ -528,8 +528,12 @@ public class LinkedHashMap<K,V>
* @return a set view of the keys contained in this map * @return a set view of the keys contained in this map
*/ */
public Set<K> keySet() { public Set<K> keySet() {
Set<K> ks; Set<K> ks = keySet;
return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks; if (ks == null) {
ks = new LinkedKeySet();
keySet = ks;
}
return ks;
} }
final class LinkedKeySet extends AbstractSet<K> { final class LinkedKeySet extends AbstractSet<K> {
...@@ -577,8 +581,12 @@ public class LinkedHashMap<K,V> ...@@ -577,8 +581,12 @@ public class LinkedHashMap<K,V>
* @return a view of the values contained in this map * @return a view of the values contained in this map
*/ */
public Collection<V> values() { public Collection<V> values() {
Collection<V> vs; Collection<V> vs = values;
return (vs = values) == null ? (values = new LinkedValues()) : vs; if (vs == null) {
vs = new LinkedValues();
values = vs;
}
return vs;
} }
final class LinkedValues extends AbstractCollection<V> { final class LinkedValues extends AbstractCollection<V> {
......
...@@ -855,7 +855,11 @@ public class TreeMap<K,V> ...@@ -855,7 +855,11 @@ public class TreeMap<K,V>
*/ */
public Collection<V> values() { public Collection<V> values() {
Collection<V> vs = values; Collection<V> vs = values;
return (vs != null) ? vs : (values = new Values()); if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
} }
/** /**
......
...@@ -865,7 +865,11 @@ public class WeakHashMap<K,V> ...@@ -865,7 +865,11 @@ public class WeakHashMap<K,V>
*/ */
public Set<K> keySet() { public Set<K> keySet() {
Set<K> ks = keySet; Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet())); if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
} }
private class KeySet extends AbstractSet<K> { private class KeySet extends AbstractSet<K> {
...@@ -914,7 +918,11 @@ public class WeakHashMap<K,V> ...@@ -914,7 +918,11 @@ public class WeakHashMap<K,V>
*/ */
public Collection<V> values() { public Collection<V> values() {
Collection<V> vs = values; Collection<V> vs = values;
return (vs != null) ? vs : (values = new Values()); if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
} }
private class Values extends AbstractCollection<V> { private class Values extends AbstractCollection<V> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册