Java 互斥与对象问题

Java 互斥与对象问题,java,multithreading,mutex,Java,Multithreading,Mutex,我在查看Collections.synhronizedMap()的java代码。我发现它有以下实现。现在我的问题是 1) 为什么要使用同步(互斥) 2) 如果我们使用synchronized(m)呢 我的理解是,如果我们进行同步(m),那么也只有一个线程能够访问映射 static class SynchronizedMap<K, V> implements Map<K, V>, Serializable { private static final long se

我在查看Collections.synhronizedMap()的java代码。我发现它有以下实现。现在我的问题是 1) 为什么要使用同步(互斥) 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);
        }
    }

在这两种情况下,一次只能有一个线程访问映射内容

最好将互斥体从映射中分离出来。如果传入的映射有其他线程在其上同步,则这不会影响此对象。将锁与映射分离可以让用户单独指定锁,因此它允许用户与其他对象共享锁

这个类的编写方式允许它从自身外部使用锁,或者将自身用作锁。为什么不明显,因为没有给出上下文,我假设有一种情况,在这个映射中需要粗粒度锁定,还有其他一些东西

我想要像这样的东西

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());
}
私有最终对象互斥体;
公共同步映射(映射映射、对象互斥){
m=地图;
this.mutex=mutex;
}
公共同步地图(地图地图){
这(映射,新对象());
}
因为这样,至少可以选择在对象的控制下独占锁

此处指的是SynchronizedMap对象


顺便说一句,它可能不使用私有锁,所以它可以支持客户端锁定

正如在另一个答案中已经指出的那样:一般来说,作为经验法则,最好有一个显式的、专用的、私有的“锁”对象,而不是通过公共方法公开同步的
(在后一种情况下,对象本身就是锁,这在某些情况下很容易导致死锁)

然而,这里的情况有点不同,因为所有这些都引用了
集合
类的私有内部类。特别是,存在显式的
互斥体
参数的主要原因是该互斥体可以在多个实例之间共享。构造器

SynchronizedMap(Map<K,V> m, Object mutex)
在这里,实际映射的互斥体也传递给子映射


因此,这里的效果是相同的互斥用于映射及其子映射。如果
SynchronizedMap
中的同步在代理映射上与
synchronized(m)

进行同步,则这是不可能的。请您详细描述一下。我在其他类中也看到过这一点,final ReentrantLock lock=this.lock;你也可以建议我阅读任何链接来充分理解这一点。请考虑我这个门外汉。它将帮助我以及其他阅读本文或试图理解当前并发场景的人。但是请看构造函数<代码>互斥=此
。大笑!在我看来,这个实现完全是一团糟。也不是说“私有”映射包含对传递给构造函数的对象的引用@AnilSharma我假设,由于整个类声明为
静态
,所以它是一个内部类,可能是有原因这样编写的,但是脱离上下文,它看起来不像是一个优秀软件设计的光辉示例。@Anil:我不知道您需要什么细节,您可以使问题更具体。@jameslarge“private”映射包含对构造函数参数的引用,因为这是映射的视图。这就是我们想要的行为。抱歉,来自java的人不需要那么多批评。它是java.util.Collections类的一段代码。基本上我是在研究集合的同步。synchronizedMap()方法。事实上,我不想粘贴超过1000行的整个类,所以只粘贴该部分。
SynchronizedMap(Map<K,V> m, Object mutex)
SynchronizedSortedMap(SortedMap<K,V> m, Object mutex) {
    super(m, mutex);
    sm = m;
}
public SortedMap<K,V> subMap(K fromKey, K toKey) {
    synchronized (mutex) {
        return new SynchronizedSortedMap<>(
            sm.subMap(fromKey, toKey), mutex);
    }
}