java.util.concurrent: external synchronize to remove map value
<p>I need to keep track of multiple values against unique keys i.e. 1(a,b) 2(c,d) etc...</p>

<p>The solution is accessed by multiple threads so effectively I have the following defined;</p>

<pre><code>ConcurrentSkipListMap&lt;key, ConcurrentSkipListSet&lt;values&gt;&gt;
</code></pre>

<p>My question is does the removal of the key when the value set size is 0 need to be synchronized? I know that the two classes are "concurrent" and I've looked through the OpenJDK source code but I there would appear to be a window between one thread T1 checking that the Set is empty and removing the Map in remove(...) and another thread T2 calling add(...). Result being T1 removes last Set entry and removes the Map interleaved with T2 just adding a Set entry. Thus the Map and T2 Set entry are removed by T1 and data is lost.</p>

<p>Do I just "synchronize" the add() and remove() methods or is there a "better" way?</p>

<p>The Map is modified by multiple threads but only through two methods.</p>

<p>Code snippet as follows;</p>

<pre><code>protected static class EndpointSet extends U4ConcurrentSkipListSet&lt;U4Endpoint&gt; {
    private static final long serialVersionUID = 1L;
    public EndpointSet() {
        super();
    }
}

protected static class IDToEndpoint extends U4ConcurrentSkipListMap&lt;String, EndpointSet&gt; {
    private static final long serialVersionUID = 1L;
    protected Boolean add(String id, U4Endpoint endpoint) {
        EndpointSet endpoints = get(id);
        if (endpoints == null) {
            endpoints = new EndpointSet();
            put(id, endpoints);
        }
        endpoints.add(endpoint);
        return true;
    }

    protected Boolean remove(String id, U4Endpoint endpoint) {
        EndpointSet endpoints = get(id);
        if (endpoints == null) {
            return false;
        } else {
            endpoints.remove(endpoint);
            if (endpoints.size() == 0) {
                remove(id);
            }
            return true;
        }
    }
}
</code></pre>
