我正在查看Collections.synhronizedMap()的java代码。我发现它已经低于实现。现在我的问题是 1)为什么我们使用synchronized(互斥) 2)如果我们使用synchronized(m)
该怎么办?我理解的是,如果我们进行同步(m),那么也只有一个线程能够访问地图。
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 = this;
答案 0 :(得分:4)
在任何一种情况下,一次只有一个线程可以访问地图内容。
将互斥锁与地图分开是更好的方式。如果传入的映射使其他线程同步,那么这不会影响该对象。将锁与地图分开可让用户单独指定锁,因此它允许用户与其他人共享锁。
这个类的编写方式是让它从外部使用锁,或者将自己用作锁。为什么不明显,因为没有给出上下文,我假设有一种情况,在这个地图上需要粗粒度锁定,而其他东西也需要。
我更喜欢像
这样的东西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对象。
答案 1 :(得分:2)
正如在另一个答案中已经指出的那样:一般而言,根据经验,最好有一个明确的,专用的私有“锁定”对象,而不是通过公共方法公开synchronized
(在后一种情况下,对象本身将成为锁定,这在某些情况下很容易导致死锁)
但是,这里的情况有点不同,因为所有这些都引用了Collections
类的私有内部类。特别是,存在明确mutex
参数的主要原因是此互斥锁可以在多个实例之间共享。构造函数
SynchronizedMap(Map<K,V> m, Object mutex)
是(仅!)在子类中调用,即在
中SynchronizedSortedMap(SortedMap<K,V> m, Object mutex) {
super(m, mutex);
sm = m;
}
只是将给定的互斥量传递给SynchronizedMap
。反过来,此构造函数在subMap
类的tailMap
,headMap
和SynchronizedSortedSet
方法中调用。例如:
public SortedMap<K,V> subMap(K fromKey, K toKey) {
synchronized (mutex) {
return new SynchronizedSortedMap<>(
sm.subMap(fromKey, toKey), mutex);
}
}
此处,实际地图的互斥锁也会传递给子地图。
因此,这里的效果是相同的互斥锁用于地图及其子地图。如果SynchronizedMap
中的同步正在委托地图上与synchronized(m)
进行同步,那么这将无法实现。