2

Thread safe Map of Queues

The above question has a design implementation VERY similar to my own. I understand why it's not thread safe, but the accepted "pattern" is throwing me for a loop. I don't quite get how to implement it or what it does in relationship to the question.

    boolean send = false;
    System.out.println("MailCenter Size Start: " + mailBox.keySet().size());
    if (parsedInput.size() == 3) {
        for (String s : writers.keySet()) {
            if (!s.equals(parsedInput.get(1))) {
                send = true;
            }
        }
        if (send) {
            mailMessage.add(noAnsiName + ": " + parsedInput.get(2));
            mailBox.putIfAbsent(parsedInput.get(1), mailMessage);
            System.out.println("Current mail message is: " + mailMessage.peek());
            out.println("SERVER You have sent mail to " + parsedInput.get(1) + ".");
        }
        System.out.println("MailCenter Size Middle: " + mailBox.keySet().size());
    } else {
        int loop = 0;
        for (Map.Entry entry : mailBox.entrySet()) {
            System.out.println(entry.getKey() + ":\t" + entry.getValue());
            System.out.println("*** LOOP STATUS *** " + loop);
            loop++;
        }
    }
teik
  • 508
  • 4
  • 26
  • Post the relevant code in your question, tell us precisely what you expect it to do and what it does instead. – JB Nizet Feb 01 '15 at 08:55
  • This is one possible application of 'compare-and-swap' pattern. Maybe, Wikipedia article will be helpful: http://en.wikipedia.org/wiki/Compare-and-swap – Victor Sorokin Feb 01 '15 at 09:02
  • I'm trying to understand the design pattern, while at the same time solving a specific issue. Edited to include my own code. – Isaac Croas Feb 01 '15 at 09:03
  • 1
    If indenting your code is good, then indenting it more is probably better. – 5gon12eder Feb 01 '15 at 09:10

1 Answers1

1

I don't quite get how to implement it or what it does in relationship to the question.

The question shows that a ConcurrentHashMap is being used. However, the variable map is being declared as a Map, so the method putIfAbsent() referenced by the accepted answer is not visible.

Map<String, ConcurrentLinkedQueue<String>> map = new ConcurrentHashMap<>();

So, in order for the answer to work, the above must be changed to declare map as a ConcurrentMap.

Now, that's a good step toward thread safety. However, just because we're using a concurrent map implementation doesn't mean a get() and subsequent put() on the map are an atomic unit of work. In other words, another thread can still change the state of the map after the current thread calls get(), but before it calls put().

The answer recommends putIfAbsent() because it ensures atomicity by wrapping the equivalent of a containsKey() call and a put() call in a synchronized block. If you also then use the return value correctly, you will have solid concurrent behavior.

gknicker
  • 5,509
  • 2
  • 25
  • 41