ConcurrentSkipListMap, how to make deleting and adding calls atomic

I have N threads that add values ​​and one removes the thread. I am thinking of a better way to synchronize adding values ​​to an existing list and deleting the list.

I think the following case is possible:

 thread 1 checked condition containsKey, and entered in else block
 thread 2 removed the value
 thread 1 try to add value to existing list, and get returns null

I think the only approach I can use is synchronization by map value, in our case it is List, when we add and when we delete

    private ConcurrentSkipListMap<LocalDateTime, List<Task>> tasks = new ConcurrentSkipListMap<>();

    //Thread1,3...N
    public void add(LocalDateTime time, Task task) {
        if (!tasks.containsKey(time)) {
            tasks.computeIfAbsent(time, k -> createValue(task));
        } else {
             //potentially should be synced
            tasks.get(time).add(task);
        }
    }
    private List<Task> createValue(Task val) {
        return new ArrayList<>(Arrays.asList(val));
    }

    //thread 2
   public void remove()
    while(true){
        Map.Entry<LocalDateTime, List<Task>> keyVal = tasks.firstEntry();
        if (isSomeCondition(keyVal)) {
            tasks.remove(keyVal.getKey());
            for (Task t : keyVal.getValue()) {
                //do task processing
            }
        }
    }
   }
+6
source share
2 answers

, remove(). , -, , head, , , .

, , , ; .

, , , ( ), ( , ).

, ConcurrentSkipListMap, , . , remove ,

public void add(LocalDateTime time, Task task) {
    tasks.merge(time, Collections.singletonList(task),
        (l1,l2) -> Stream.concat(l1.stream(),l2.stream()).collect(Collectors.toList()));
}

public void remove() {
    for(Map.Entry<LocalDateTime, List<Task>> keyVal : tasks.entrySet()) {
        final List<Task> values = keyVal.getValue();
        if(isSomeCondition(keyVal) && tasks.remove(keyVal.getKey(), values)) {
            for (Task t : values) {
                //do task processing
            }
        }
    }
}

, , , . merge(time, Collections.singletonList(task), … , . (l1,l2) -> Stream.concat(l1.stream(),l2.stream()).collect(Collectors.toList()) , . , , , , .

remove remove(key, value), , - . , , , . remove(key, value) , ; . , isSomeCondition(keyVal) , isSomeCondition(keyVal) , , , isSomeCondition. , isSomeCondition , .

+1

add merge, , , .

add merge, .

SomeLock lock ... 
public void add(LocalDateTime time, Task task) {
    lock.lock();
    tasks.merge...
    lock.unlock();
}

remove. , , ConcurrentSkipListMap.

, ConcurrentHashMap - merge, , .

+3

All Articles