我正在查看 Collections.synhronizedMap() 的 java 代码。我发现它有以下实现。现在我的问题是 1) 为什么我们要使用同步(互斥锁) 2) 如果我们使用 synchronized(m) 会怎样
我的理解是,如果我们执行 synchronized(m),那么也只有一个线程能够访问 map 。
static class SynchronizedMap<K, V> implements Map<K, V>, Serializable {
private static final long serialVersionUID = 1978198479659022715L;
private final Map<K, V> m;
final Object mutex;
SynchronizedMap(Map<K, V> map) {
m = map;
mutex = this;
}
SynchronizedMap(Map<K, V> map, Object mutex) {
m = map;
this.mutex = mutex;
}
public void clear() {
synchronized (mutex) {
m.clear();
}
}
public boolean containsKey(Object key) {
synchronized (mutex) {
return m.containsKey(key);
}
}
public boolean containsValue(Object value) {
synchronized (mutex) {
return m.containsValue(value);
}
}
public Set<Map.Entry<K, V>> entrySet() {
synchronized (mutex) {
return new SynchronizedSet<Map.Entry<K, V>>(m.entrySet(), mutex);
}
}
@Override
public boolean equals(Object object) {
synchronized (mutex) {
return m.equals(object);
}
}
编辑:我想要一些与这个问题相关的澄清
1) Java 的this 关键字用于引用使用它的方法的当前实例。因此,如果我将 mutex 放在这个关键字上,那么这是否意味着我们将锁定对象的当前实例或者我们将锁定线程的当前实例?如果有人能更全面地解释以下语句的含义,我将不胜感激
mutex = this;
最佳答案
在任何一种情况下,一次只有一个线程可以访问 map 内容。
将互斥锁与 map 分开是更好的风格。如果传入的映射有其他线程在其上同步,则不会影响此对象。将锁与 map 分开可以让用户单独指定锁,因此它允许用户与其他东西共享锁。
此类的编写方式允许它从自身外部使用锁,或者将自身用作锁。为什么不明显,因为没有给出上下文,我假设有一种情况,在这个 map 和其他东西上需要粗粒度的锁定。
我更喜欢这样的东西
private final Object mutex;
public SynchronizedMap(Map<K,V> map, Object mutex) {
m = map;
this.mutex = mutex;
}
public SynchronizedMap(Map<K,V> map) {
this(map, new Object());
}
因为这样至少可以选择在对象的控制下独占锁定。
this
这里指的是 SynchronizedMap 对象。
顺便说一句,它可能不使用私有(private)锁,因此它可以支持客户端锁定。
关于java - 互斥与对象问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28978373/