怎么做"与资源同步"获取锁定对象的位置也必须同步?

时间:2015-10-06 21:53:41

标签: java multithreading parallel-processing synchronization synchronized

我有一个Map<String, Mutex> m我想锁定Mutex,同时还要确保获取锁的行为是线程安全的:

//Assuming till here m.get(key) return a non-null value
synchronized (Mutex mtx = m.get(key)) {
  mtx.count++;
  //...
}

Java无法保证以下内容

Mutex mtx = m.get(key);
synchroinzed (mtx) {
  //thread 2 may acquire lock before thread 1 even thread 1 execute first
}

,两者都不是

synchronized (m.get(key)) {
  Mutex mtx = m.get(key); 
  //mtx could be null if other threads remove the key between 2 statements
  //because lock is only acquired on m.get(key), not m itself
}

我怎样才能安全地实现这个目标?

编辑:

我现在的确切代码:

public static <T, V> void lock (Map<T, Mutex<V>> mm, T uniqueKeyValue1, long waitMs) throws Mutex.WaitTimeoutException, InterruptedException {

    synchronized ( MapUtils.putIfAbsentRetNewVal(mm, uniqueKeyValue1, new Mutex<V>()) ) {

        Mutex<V> m = mm.get(uniqueKeyValue1);

        if (m.getLockCount() == 0) {
            m.incrementLockCount();
        }
        else {
            m.incrementLockCount();

            m.wait(waitMs);

            if (m.getValue() == null) {
                throw new Mutex.WaitTimeoutException();
            }
        }
    }

}

3 个答案:

答案 0 :(得分:1)

这是一个非问题,它与with-resources没有任何关系。使用选项2.您要求的不会解决该问题。您需要的不是有资源,而是可以在地图上同步,然后在互斥锁上同步,然后在地图上释放同步。由于静态作用域,您无法使用同步。

你需要的是另一个Mutex。或者,接受比赛。这是良性的。您不关心首先执行哪个线程。

答案 1 :(得分:0)

语言不需要&#34;与资源同步&#34;构造因为JVM保证在同步块退出时它将释放锁。

答案 2 :(得分:0)

在这种情况下,您必须锁定地图,以便在当前线程使用它(m.get(key))时没有其他线程可以修改它,执行您的操作然后释放锁定。

Map<String, Mutex> m = ...
synchronized( m ) { // only a single thread can access m now 
   Mutex mtx = m.get(key);
   mtx.count++;
} // releases the lock