accessing a variable in a thread, coming from a variable inside another thread

edited February 2017 in Questions about Code

Hi all, is some days i'm doing experiments on running threads in parallel. Except the fact that probably this is not the best way to do this, since would be possible to point some external variable, i really don't understand why, if i try to access a variable inside a runnable implementation it works, but it don't if this implementation is trying to do the same:

class0 c0;

void setup() {
  size(200, 200);

  c0 = new class0();
  new Thread(c0).start();
}

void draw() {

  background(200);
  text(c0.dataToAccess, 30, 30);
}

class class0 implements Runnable {
  public int dataToAccess;
  public int interations = 0;

  class1 c1;

  class0() {
    c1 = new class1();
    new Thread(c1).start();
  }

  //@Override
    public void run() {
    while (!c1.done) {
      this.dataToAccess =c1.dataToAccess;
    //  println("iteration n" + interations++);
    }
  }
}

class class1 implements Runnable {
  public int dataToAccess;
  public boolean done = false;

  //@Override
    public void run() {
    for (int i = 0; i<=100; i++)
    {
      dataToAccess++;
      delay(500);
       println("iteration n° " + i);
    }
    done = true;
  }
}

Answers

  • edited February 2017

    Sorry, I'm not getting what exactly isn't working? :|
    The fact any class is Runnable or not doesn't change in any way the scope of its members.

    BtW, I've made some small tweaks in your code just so I could study it better: B-)

    // https://forum.Processing.org/two/discussion/20991/
    // accessing-a-variable-in-a-thread-coming-
    // from-a-variable-inside-another-thread#Item_1
    
    // 2017-Feb-25
    
    Class0 c0;
    
    void setup() {
      fill(-1);
      textSize(050);
      textAlign(CENTER, CENTER);
      new Thread(c0 = new Class0()).start();
    }
    
    void draw() {
      background(0100);
      text(c0.dataToAccess, width>>1, height>>1);
    }
    
    class Class0 implements Runnable {
      final Class1 c1;
      int dataToAccess;
    
      Class0() {
        new Thread(c1 = new Class1()).start();
      }
    
      @Override void run() {
        while (!c1.done) {
          dataToAccess = c1.dataToAccess;
          delay(10);
        }
      }
    }
    
    class Class1 implements Runnable {
      int dataToAccess;
      boolean done;
    
      @Override void run() {
        for (int i = 0; i < 30; delay(500)) {
          ++dataToAccess;
          println("iteration nº", ++i);
        }
        done = true;
      }
    }
    

    But yet, you still need to explain further what's exactly wrong. :-\"

  • Well, actually yours is written in a more elegant way. Actually my problem is that the Class0 was unable to access the dataToAccess into Class1, till i've introduced on my old code the same delay you added into the Class0 run() at line 32. Can be a concurrency access problem? Would be possible as well to use a synchronized variable or that is just for methods? Also, you declared the Class1 like final, is that for efficiency like it would be for a variable? So many questions, i know :-)

  • Like this for example?

    // https://forum.Processing.org/two/discussion/20991/
    // accessing-a-variable-in-a-thread-coming-
    // from-a-variable-inside-another-thread#Item_1
    
    // 2017-Feb-25
    
    Class0 c0;
    
    void setup() {
      fill(-1);
      textSize(050);
      textAlign(CENTER, CENTER);
      new Thread(c0 = new Class0()).start();
    }
    
    void draw() {
      background(0100);
      text(c0.dataToAccess, width>>1, height>>1);
    }
    
    class Class0 implements Runnable {
      final Class1 c1;
      int dataToAccess;
    
      Class0() {
        new Thread(c1 = new Class1()).start();
      }
    
      @Override void run() {
        while (!c1.done) {
          dataToAccess = c1.accessTheData();
          //delay(10);
        }
      }
    }
    
    class Class1 implements Runnable {
      int dataToAccess;
      boolean done;
    
      @Override void run() {
        for (int i = 0; i < 30; delay(500)) {
          ++dataToAccess;
          println("iteration nº", ++i);
        }
        done = true;
      }
    
      public synchronized int accessTheData(){
       return dataToAccess; 
      }
    }
    
  • edited February 2017

    ... till I've introduced on my old code the same delay() you added into the Class0 run() at line 32.

    I confess the 1st thing I did prior to run your code for the 1st time was adding delay(10);. :P
    B/c I know that an "infinite" loop w/o doing nothing else other than checking a variable would "fry" the CPU core running that Thread! :-SS Therefore I've unintentionally skipped your "bug" completely. :-\"

    Can be a concurrency access problem?

    In Java, each Thread got its own piece of RAM. And there's also the main RAM.
    In order for a Thread to "see" the current value of some field which was just mutated by another Thread, that field needs to be updated to the main RAM 1st. L-)

    My theory is that perhaps w/o any delay(), there wouldn't be any time gap for the transfer from main RAM to the always-busy Thread's RAM to occur. :-?

    Would be possible as well to use a synchronized variable or that is just for methods?

    synchronized is only for methods and {} blocks.
    For non-final fields we can declare them as volatile w/ some small performance "sacrifice". $-)
    final fields don't need volatile b/c they can't be reassigned after all. \m/

    Also, you declared the Class1 like final. Is that for efficiency like it would be for a variable?

    Well, in some cases it might give more room to Java's VM to be more aggressive towards optimization, given it's guaranteed the value stored in the variable won't change ever! :)>-

  • A really gr8 series of articles about Java's concurrency: ~O)
    http://Tutorials.Jenkov.com/java-concurrency/index.html

Sign In or Register to comment.