Java – iterative weakhashmap

I also use weakhashmap I want to implement fine-grained locking based on an integer parameter; If thread a needs to modify the resource identified by integer a and thread B performs the same operation on the resource identified by integer B, synchronization is not required However, if two threads use the same resource, thread C also uses the resource identified by the integer A. of course, threads a and C need to synchronize on the same lock

When no more threads need resources with ID x, you can delete lock in the map with key = X However, another thread can enter and try to use the lock in map for id = x, so global synchronization is required when adding / removing locks (this will be the only place where each thread must synchronize, regardless of the integer parameter) however, a thread does not know when to delete the lock because it does not know that it is the last thread to use the lock

That's why I use weakhashmap: when ID is no longer used, key value pairs can be deleted when GC needs them

In order to ensure that I have strongly referenced the keywords of existing entries and the object references that form the mapping keywords, I need to iterate the keyset of the map:

synchronized (mrLocks){
    // ... do other stuff
    for (Integer entryKey : mrLocks.keySet()) {
        if (entryKey.equals(id)) {
            key = entryKey;
            break;
        }
    }
    // if key==null,no thread has a strong reference to the Integer
    // key,so no thread is doing work on resource with id,so we can
    // add a mapping (new Integer(id) => new reentrantlock()) here as
    // we are in a synchronized block. We must keep a strong reference
    // to the newly created Integer,because otherwise the id-lock mapping
    // may already have been removed by the time we start using it,and 
    // then other threads will not use the same Lock object for this
    // resource
}

Now, can the contents of the map be changed during iteration? I don't think so, because by calling mrlocks Keyset (), I created a powerful iteration scope that references all keys Is that right?

Solution

Since the API has no assertion about keyset (), I recommend using the following cache:

private static Map<Integer,Reference<Integer>> lockCache = Collections.synchronizedMap(new WeakHashMap<>());

public static Object getLock(Integer i)
{
    Integer monitor = null;
    synchronized(lockCache) {
        Reference<Integer> old = lockCache.get(i);
        if (old != null)
            monitor = old.get();

        // if no monitor exists yet
        if (monitor == null) {
            /* clone i for avoiding strong references 
               to the map's key besides the Object returend 
               by this method.
            */ 
            monitor = new Integer(i);
            lockCache.remove(monitor); //just to be sure
            lockCache.put(monitor,new WeakReference<>(monitor));
        }

    }

    return monitor;
}

In this way, you reference the monitor (the key itself) when it is locked and allow the GC to complete it when it is no longer in use

Editor: after the discussion on payload, I came up with a solution with two caches:

private static Map<Integer,Reference<reentrantlock>> lockCache = new WeakHashMap<>();
private static Map<reentrantlock,Integer> keyCache = new WeakHashMap<>();

public static reentrantlock getLock(Integer i)
{
    reentrantlock lock = null;
    synchronized(lockCache) {
        Reference<reentrantlock> old = lockCache.get(i);
        if (old != null)
            lock = old.get();

        // if no lock exists or got cleared from keyCache already but not from lockCache yet
        if (lock == null || !keyCache.containsKey(lock)) {
            /* clone i for avoiding strong references 
               to the map's key besides the Object returend 
               by this method.
           */ 
            Integer cacheKey = new Integer(i); 
            lock = new reentrantlock();
            lockCache.remove(cacheKey); // just to be sure
            lockCache.put(cacheKey,new WeakReference<>(lock));
            keyCache.put(lock,cacheKey);
        }                
    }

    return lock;
}

As long as there is a strong reference to the payload (lock), a strong reference to the mapped integer in the keycache will avoid deleting the payload from the lockcache cache cache

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>