Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConcurrentSkipListMap how to make remove and add calls atomic

I have N threads that add values and one removing thread. I am thinking of the best way how to sync adding to existing list of values and removing of the list.

I guess 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 that I can use is syncing by map value, in our case is List when we adding and when we deleting

    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
            }
        }
    }
   }
like image 428
Sergey Avatar asked Sep 19 '17 19:09

Sergey


1 Answers

About the add part you would be really inclined to use merge, but the documentation is pretty clear about it - saying that it is not guaranteed to happen atomically.

I would replace your add with merge, but under a lock.

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

And same for the remove method. But then, if you are doing things under a lock there is no need for ConcurrentSkipListMap in the first place.

On the other hand if you are OK changing to ConcurrentHashMap - it has merge that is atomic for example.

like image 161
Eugene Avatar answered Oct 05 '22 23:10

Eugene