takotsubo
takotsubo

Reputation: 746

Java Safe Multithreading

i have a couple of questions about multithreading (i want to do my small project safe and fast).

I have a class Library. I will add users requests to a file.

public static volatile HashMap<String, GooglePlayGame> games = new HashMap<>(500);

At each app start I initialize this hashmap using a file (json+Jackson) in static block:

static {
    TypeFactory typeFactory = mapper.getTypeFactory();
    MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, GooglePlayGame.class);
      try {
          games = mapper.readValue(new File("games.json"), mapType);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

Each user's request (with special command /library) will be processed and then new pair "key-value" will be added to global hashmap, of course if key doesnt exists (check with containsKey). Then work with this hashmap (not from file).

Then i want to write new pairs into my file. For this i want to create a new thread, like this:

Thread thread = new Thread(() -> {
            try {
                mapper.writeValue(new File("games.json"), games);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        thread.start();

Questions:

1) Does "volatile" help? Does it guarantee that when writing to file I will always see all last added pairs?

2) What if.. Write to file not every new pair, but every new 10 pairs? How to do this? Use CountDownLatch? if yes, how to properly organize this? Im kinda bad at multihreading. But what if program will be crashed and i got 9 new requests, these pairs will be lost!

3) By the way, am I creating a new file here or just overwriting the old one? If i'm always create new file, this is kinda bad. Jackson creating new file or overwriting old one?

Upvotes: 0

Views: 44

Answers (2)

Solomon Slow
Solomon Slow

Reputation: 27210

Here's the main reason why you would ever use the volatile keyword:

If you have some volatile ... x; then whatever thread A did before assigning x = v; will be visible to thread B after thread B has observed the assignment.

final XType v = ...;
volatile XType x = ...some value other than v...;
AType a;
BType b;
CType c;

In thread A:

a = ...;
b = ...;
x = v;
c = ...;

In thread B:

while (x != v) {
    ...sleep, or spin, or maybe do some useful work...
}
...guaranteed to see the new values of a, and b here.
...No guarantee about c. Could see the old value or the new value.

But note! What triggered the behavior was the assignment x = v;

Your program initializes the volatile variable, games, but there is no place where your program ever assigns games. Nothing in your program ever triggers the volatile-ness of games. The keyword has no effect in your particular example.

Upvotes: 1

Amongalen
Amongalen

Reputation: 3131

1) In this case volatile keyword won't give you want you expect. It might be a little bit misleading when you search for what it does. You can find that "volatile keyword guarantees that all writes to the variable are visible to all threads". What it means tho is that when you assign a new value (new object) to the variable it will be visible. However, if you change an object that is assigned to that variable, those changes won't necessarily be visible to all the threads.

In your case you modify the Hashmap and not the variable, so it might not be visible. You should consider using some dedicated build-in collection that is thread-safe, like ConcurrentHashMap

2) You can't really ensure that all the data will be written to the file in case of a crash. It is always safer to write the data after each entry but it depends on how often it happens. If it's like once a minute the it's fine to write 1 at the time, if it's thousands of time a second then you should consider some bulk writing.

3) I think it should be quite easy to test it yourself. Plus it isn't really related to the main question which is about multithreading.

Upvotes: 1

Related Questions