user133406
user133406

Reputation: 11

Synchronization of ConcurrentHashMap modifiers

I would like to cache some IO with the help of ConcurrentHashMap. The modification on the binary file should be reflected in cache as well. Since the cache is going to be used by multiple threads all IO operations are synchronized. Modifications of map go inside the same synchronized block. Which roughly looks like:

synchronized (file) {
    file.deleteRecord(index)
    map.remove(index);
}

and

synchronized(file) {
    file.writeRecord(index, record);
    map.put(index, record);
}

Both map and file are private and are not seen from outside the cache-class.

Is thread-safety preserved if cache reads, namely map.get(index), go without the synchronized block?

As I mentioned earlier, ConcurrentHashMap is used as map implementation.

Upvotes: 1

Views: 3946

Answers (4)

Jed Wesley-Smith
Jed Wesley-Smith

Reputation: 4706

Well, as everyone here says, this is thread-safe in that you have a happens-before relationship between the write to the cache and the read from the cache, but that may be meaningless depending on what other guarantees you are hoping for.

For instance, unless you fsync the file there's no guarantee the record will be written to disk, so you may not read the record from disk (depending on the file-system and a few other factors). There is also no happens-before relationship between the writeRecord/deleteRecord and map write and the read from the map, so the JMM doesn't guarantee that you read something from the map that has definitely been written to the file.

You do get a guarantee that the state of the index and record objects as written will be what will be read, although if either of these are mutable then that may be a fairly useless guarantee.

Upvotes: 0

user58804
user58804

Reputation: 589

Yes, ConcurrentHashMap is thread safe, so reading (or writing) does not require any locking on your part.

However, in your example, you might end up with the following sequence of events:

file.deleteRecord(index);
map.get(index) // returns the mapping for index even though it has been deleted from file
map.remove(index);

(the same for writeRecord/put). This might or might not be a problem in your case.

Upvotes: 1

Stu Thompson
Stu Thompson

Reputation: 38878

Yes, thread safety is preserved down to the map references, thanks to the ConcurrentHashMap implementation.

The objects you store in the map are another story.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1501043

Yup. This is basically the point of ConcurrentHashMap. From the documentation:

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset.

and from the package documentation:

A concurrent collection is thread-safe, but not governed by a single exclusion lock. In the particular case of ConcurrentHashMap, it safely permits any number of concurrent reads as well as a tunable number of concurrent writes.

(Both of those documentation pages have much more detail, of course. They're worth reading carefully.)

Upvotes: 5

Related Questions