I'd like some wisdom regarding a recent multithreading idea of mine. Here goes:
Suppose I have the following (pseudo) class whose run() method is chugging away forever on some thread. Other threads will at random times change the state of the Foo instance using setState(). The work that run() is doing only involves reading the state variables, no writing, and the state must not change during one execution of the while statement (example: drawing on a bitmap).
In this case, having 2 copies of the state variables seems to prevent a lot of potential blocking (since if I only had one copy of shared state variables, I would have to synchronize everything in the while loop (using stateLock) and outside threads may not get the chance to change the state). Questions after the code break.
class Foo {
Object stateLock = new Object();
private float my1, my2, my3;
private float sh1, sh2, sh3; // sh stands for shared
public void setState(...) {
synchronized (stateLock) {
// modify sh1, sh2, or sh3 here
}
}
private void updateState() {
synchronized (stateLock) {
// set my1=sh1, my2=sh2, my3=sh3
}
}
public void run() {
while(true) {
updateState();
// then do tons of stuff that uses my1,my2,my3 over and over...
...
}
}
}
Any holes in this logic? Is there a "standardized" or smarter way of doing this? What if there are tons of state variables? Worse, what if state variables are custom objects that don't copy easily (e.g. in java where variables of custom objects are references)?
By the way, this comes from my current work with a SurfaceView in Android.
There is a simpler way of fixing this is:
private volatile float sh1, sh2, sh3; // note "volatile"
In the java memory model, threads are allowed to cache values from other threads.
The volatile keyword means that all threads must use the same variable value (ie all reference the same memory location of the variable). When used with primitives, it means you don't need synchronization (although with 64-bit primitives, of which float is not one, you may not need synchronization, depending on your JVM being 32- or 64-bit)
You may want to watch partial/inconsistent updates - where some of the sh variables are updated when another thread reads them. You may want to synchronize the updates to maintain consistent state by making your updates to multiple sh variables "atomic".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With