Alex Rivera | Logout

Java concurrency scenario -- do I need synchronization or not?

Asked 2008-11-18T22:07:54.320
16

Here's the deal. I have a hash map containing data I call "program codes", it lives in an object, like so:

Class Metadata
{
    private HashMap validProgramCodes;
    public HashMap getValidProgramCodes() { return validProgramCodes; }
    public void setValidProgramCodes(HashMap h) { validProgramCodes = h; }
}

I have lots and lots of reader threads each of which will call getValidProgramCodes() once and then use that hashmap as a read-only resource.

So far so good. Here's where we get interesting.

I want to put in a timer which every so often generates a new list of valid program codes (never mind how), and calls setValidProgramCodes.

My theory -- which I need help to validate -- is that I can continue using the code as is, without putting in explicit synchronization. It goes like this: At the time that validProgramCodes are updated, the value of validProgramCodes is always good -- it is a pointer to either the new or the old hashmap. This is the assumption upon which everything hinges. A reader who has the old hashmap is okay; he can continue to use the old value, as it will not be garbage collected until he releases it. Each reader is transient; it will die soon and be replaced by a new one who will pick up the new value.

Does this hold water? My main goal is to avoid costly synchronization and blocking in the overwhelming majority of cases where no update is happening. We only update once per hour or so, and readers are constantly flickering in and out.

Edit
Report

2 Answers

2

I think your assumptions are correct. The only thing I would do is set the validProgramCodes volatile.

private volatile HashMap validProgramCodes;

This way, when you update the "pointer" of validProgramCodes you guaranty that all threads access the same latest HasMap "pointer" because they don't rely on local thread cache and go directly to memory.

answered 2008-11-18T22:23:10.717
-3

If I read the JLS correctly (no guarantees there!), accesses to references are always atomic, period. See Section 17.7 Non-atomic Treatment of double and long

So, if the access to a reference is always atomic and it doesn't matter what instance of the returned Hashmap the threads see, you should be OK. You won't see partial writes to the reference, ever.


Edit: After review of the discussion in the comments below and other answers, here are references/quotes from

Doug Lea's book (Concurrent Programming in Java, 2nd Ed), p 94, section 2.2.7.2 Visibility, item #3: "

The first time a thread access a field of an object, it sees either the initial value of the field or the value since written by some other thread."

On p. 94, Lea goes on to describe risks associated with this approach:

The memory model guarantees that, given the eventual occurrence of the above operations, a particular update to a particular field made by one thread will eventually be visible to another. But eventually can be an arbitrarily long time.

So when it absolutely, positively, must be visible to any calling thread, volatile or some other synchronization barrier is required, especially in long running threads or threads that access the value in a loop (as Lea says).

However, in the case where there is a short lived thread, as implied by the question, with new threads for new readers and it does not impact the application to read stale data, synchronization is not

answered 2008-11-18T22:35:51.630

Your Answer