[java] Stupidity check with volatiles and multithreading

Started by
8 comments, last by tebriel 15 years, 8 months ago
Situation: A server feed sending data to clients every X seconds is running in a separate thread. Another thread, handling requests from clients, modifies the data that this thread routinely sends out to all connected clients. The "feed thread" never modifies the data it sends out, it only sends it over the wires. The data being sent consists of a single object that contains both primitives and other composite objects, most of which are lists of composite objects. I'm trying to decide whether I need to declare the references within this object (and the main object itself) volatile. Or--maybe it's not that simple and I need to lock that crap down better. Or, maybe I'd be okay without even using volatile? (Kinda doubt it.) The other (non feed) thread won't be modifying the data very often (just based on occasional user input for the most part) but I'm concerned that the feed thread will try to read data while the other thread is in the middle of altering it, and maybe send it to clients while it's in an invalid state. I need a few outside opinions here to confirm my suspicions. And no, this is not a homework question or something, I graduated college awhile back, farther back than I care to think about. LOL
Advertisement
The volatile keyword is pretty much useless for data structures*.

You need a mutex to protect your data.
Before modifying or reading the data, you need to lock the mutex, after you've finished, unlock the mutex. This means that only one thread can be accessing the data at a time, making sure that it's always in a valid state.

* Volatile only protects individual primitives from concurrent access, not entire data structures. So even with volatile members, your composite object itself could be read in a 'half modified' state.

Use a mutex ;)
[EDIT] It seems Java doesn't provide a simple Mutex... Use a semaphore ;)

[Edited by - Hodgman on August 13, 2008 11:19:33 PM]
Yeah I thought that would be too easy, just couldn't nail down a concrete reason. Computers suck, they need to be figuring this stuff out on their own from now on. :p
Have you looked at using synchronized methods or synchronized blocks of code?
Quote:Original post by Tebriel
Yeah I thought that would be too easy, just couldn't nail down a concrete reason. Computers suck, they need to be figuring this stuff out on their own from now on. :p


OpenMP, TBB, Stackless Python, Erlang, ....

Just use the right language.
You're saying those solve "all" multithreading issues? I have to be just a little skeptical there.

But even if they can do MT magic, they can't have the community and free functionality that Java has in other areas, that's pretty huge.
Quote:Original post by Shabadoo
Have you looked at using synchronized methods or synchronized blocks of code?


Well yeah, that was what I was going to end up doing had I gotten no feedback. I was just considering using Semaphore with MAX_AVAILABLE=1, to make writing the code a little cleaner, but I don't think it does. Yeah wouldn't synchronized be easier? I think that's what I really need.
Actually even better, I think I'm going to use a "Guarded Block" to do this.

http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html

The 'feed' is a consumer and the data altering thread is a producer, looks good. Still researching... hmm.

[Edited by - Tebriel on August 14, 2008 12:56:46 PM]
OpenMP/TBB aren't languages...

I'm guessing that Synchronized methods won't help your situation, because they just stop two threads from updating / reading the object at once. This means that they can still 'take turns' in updating/reading the object - so if it takes multiple updates to change the object from one valid state to another, then it would still be possible for the object to be read in an invalid/intermediate/half-updated state.

I haven't used synchronised blocks before, so I can't comment on them.

That Guarded Blocks / Producer-Consumer example looks pretty useful.
The only difference I'm aware of with sync blocks is that they allow you to lock on any given object instead of the one running the currently executing sync method.

I'm actually not sure if multiple updates (which invalidate my model's state in between) will occur here. Since it's fairly probable, I should probably guard against it. I think Guarded Blocks will be sufficient for that.

The example on that page also ensures that the consumer thread (sending data to clients for me) sends out it's updates before any further updates are permitted, which I also like. So each change to the data should be a separate client update, rather than possibly combining several changes into one client update.

This topic is closed to new replies.

Advertisement