Avoid locking with copies of state variables?

I need wisdom regarding a recent multithreaded idea. Here:

Suppose I have the following (pseudo) class, the method is run()forever interrupted on some thread. Other threads will randomly change the state of the instance Foousing setState(). The work performed run()includes only reading state variables, no writing, and the state should not change during one execution of the while statement (example: drawing on a bitmap).

In this case, having two copies of the state variables seems to prevent a lot of potential blocking (because if I had only one copy of the state variables, I would have to synchronize everything in the while loop (using stateLock) and the external threads cannot get a chance change state). Questions after breaking the code.

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 to do this? What if there are tons of state variables? Worse, what if state variables are user objects that are not easily copied (for example, in java, where user object variables are links)?

By the way, this comes from my current work with SurfaceView on Android.

+3
source share
2

, . , , , .

( ..). setState , . ( , setState , ), AtomicReference , .

class Foo {
    private final AtomicReference<State> state = new AtomicReference<State>(new State(0, 0, 0));

    private void setState(float x1, float x2, float x3) {
        State current;
        State updated;
        do {
            current = state.get();
            // modify the values
            float sh1 = current.sh1 + x1;
            float sh2 = current.sh2 + x2;
            float sh3 = current.sh3 + x3;
            updated = new State(sh1, sh2, sh3);
        } while (!state.compareAndSet(current, updated));
    }

    public void run() {
        while (true) {
            State snapshot = state.get();
            // then do tons of stuff that uses sh1, sh2, sh3 over and over...
        }
    }

    private class State {
        public final float sh1, sh2, sh3;

        State(float sh1, float sh2, float sh3) {
            this.sh1 = sh1;
            this.sh2 = sh2;
            this.sh3 = sh3;
        }
    }
}

, :

class Foo {
    private volatile State state = new State(0, 0, 0);

    private void setState(float sh1, float sh2, float sh3) {
        state = new State(sh1, sh2, sh3);
    }

    public void run() {
        while (true) {
            State snapshot = state;
            // then do tons of stuff that uses sh1, sh2, sh3 over and over...
        }
    }

    private class State {
        public final float sh1, sh2, sh3;

        State(float sh1, float sh2, float sh3) {
            this.sh1 = sh1;
            this.sh2 = sh2;
            this.sh3 = sh3;
        }
    }
}
+2

:

private volatile float sh1, sh2, sh3;  // note "volatile"

java . volatile , (.. ). , ( 64- , float ), , JVM, 32 64 -)

/ - sh , . , , sh "".

+3

All Articles