12

Given the following code:

public class FooBar { 

  public static volatile ConcurrentHashMap myConfigData  = new ConcurrentHashMap();      

}

public class UpdaterThread implements Runnable { 

  public void run() {
    //Query the Data from the DB and Update the FooBar config Data
    FooBar.myConfigData = ConfigDataDAO.getLatestConfigFromDB();
  }

}

The Thread-Class will update the myConfigData Membervariable regularly (via an Executor every 5 minutes). Is the setting of of myConfigData in the "external" Thread threadsafe (atomic), or do I have to synchronize every Read and Write operation to the myConfigData Variable?

EDIT: The question is not whether ConcurrentHashMap is threadsafe (it is according to javadoc) but rather the setting of the ConcurrentHashMap itself in the myConfigData Member variable. This variable might be read and written "at once" by several threads so the question is whether the setting is atomic or not. I think this can be generalized to "Is the setting of a Java reference variable atomic or not?".

(I also made it volatile. This is a different issue and has nothing to do with atomicity - my question - but rather "visibility in other threads" and the happens-before relationship.)

miguel
  • 16,205
  • 4
  • 53
  • 64

5 Answers5

22

Replacing references is safe. See Java language Specification:

When a thread uses the value of a variable, the value it obtains is in fact a value stored into the variable by that thread or by some other thread. This is true even if the program does not contain code for proper synchronization. For example, if two threads store references to different objects into the same reference value, the variable will subsequently contain a reference to one object or the other, not a reference to some other object or a corrupted reference value. (There is a special exception for long and double values; see §17.4.)

Wolfgang
  • 3,460
  • 3
  • 28
  • 38
  • 3
    @unknown: the quoted text does not say what you think it says!! In fact, the next bullet in the JLS says this: "In the absence of explicit synchronization, an implementation is free to update the main memory in an order that may be surprising. Therefore the programmer who prefers to avoid surprises should use explicit synchronization." – Stephen C Aug 29 '09 at 13:46
  • 2
    @unknown: the only reason that the OP's code is safe is that he has declared the variable as `volatile`. – Stephen C Aug 29 '09 at 13:48
  • 5
    @Stephen I think the main point of the question was about the atomicity of the assignment. That's why I quoted this part of the spec. If I understand correctly, then this atomicity is guaranteed even if volatile is not used. However then it may happen, that other threads will never see an update to the variable and continue to see the "old" reference. However a thread will never see "a reference to some other object or a corrupted reference value". – Wolfgang Aug 29 '09 at 15:07
  • @Stephen: Check the source for String hashCode(). You will find hash=h which is considered thread safe without hash being volatile. – user1944408 Dec 07 '15 at 14:33
  • 2
    @user1944408 - and your point is .... ? Yes, there are cases where you prove that code will work correctly without either use of `volatile` or explicit synchronization. In this case, it works because there are exactly two possible states for `hash` (the JLS says so), and the code gives the correct answer in either state. – Stephen C Dec 07 '15 at 14:50
2

volatile guarantees atomicity, visibility and acts as a 'memory barrier' (google for it, if you want to know what that means) - at least since Java 5. Therefore it does exactly what you want.

Kutzi
  • 1,295
  • 1
  • 15
  • 19
0

ConcurrentHashMp is:

A hash table supporting full concurrency of retrievals and adjustable expected concurrency for updates. This class obeys the same functional specification as Hashtable, and includes versions of methods corresponding to each method of Hashtable. However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.

The javadocs say that it's thread safe.

Seems like a lot of work and CPU cycles to set configuration. Is it truly this dynamic? Or do you change once a month and just need a service bounce when you do?

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • Thanks for your answer! I tried to make my question more clear and edited my question. –  Aug 29 '09 at 11:54
0

If by update you mean overwrite an entry inside the ConcurrentHashMap:

FooBar.myConfigData.put(somekey, somevalue);

Then it is definitely thread safe, as duffymo said.

If you want to overwrite the myConfigData variable with a new value:

FooBar.myConfigData = new ConcurrentHashMap();

It is also thread-safe, as you have correctly labelled the variable as volatile. The volatile keyword means that multiple threads can access the same variable safely and atomically.

EDIT: The Question is not wether ConcurrentHashMap is threadsafe (it is according to javadoc) but rather the Setting of the ConcurrentHashMap itself in the myConfigData Member variable. This variable might be read and written "at once" by several threads so the question is, if the setting is atomic or not. I think this can be generalized, is the Setting of a Java Reference variable atomic or not.

(I also made it volatile. This is a different issue and has nothing to do with atomicity (my question) but rather "visibility in other threads" and the happens before relationship).

Actually 'volatile' is for atomicity, nothing affects visibility, a public variable will always be visible to any thread.

Community
  • 1
  • 1
Will
  • 1,711
  • 1
  • 12
  • 17
-1

You could alway use AtomicReference if you feel unsure.

Although I think in your case volatile schould be enough.

zckman
  • 437
  • 3
  • 6