0

I have two threads, one setting a variable of a class, and the other one accessing the variable by a get method.

public class Parent {
    private int value = -1

    public int getValue()
      return this.value;
    }

    public void setValue(int value){
      this.value = value;
    }

    private class UpdatingVaribale extends Thread {

    public void run() {
      while (!Thread.currentThread().isInterrupted()) {
        try {
            setValue(2);
            Thread.currentThread().interrupt();
        }
      } 
    }
}

private class GettingVaribale extends Thread {

    public void run() {
      while (getValue == -1) {
        try{
            System.out.println(getValue);
            Thread.sleep(500);
         } catch (InterruptedException e) {
         }
       }
       System.out.println(getValue); 
    }
}

The problem is that the condition of the while loop in the second thread is always true. The System.out.println(getValue) always prints -1. I am wondering why the second thread doesn't get the new value of value which is 2. I don't think the synchronized matters here since one thread is setting a variable and the other one just accessing the variable.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
Self
  • 147
  • 2
  • 16
  • Possible duplicate of [Do you ever use the volatile keyword in Java?](http://stackoverflow.com/questions/106591/do-you-ever-use-the-volatile-keyword-in-java) – shmosel Sep 23 '16 at 21:17
  • 2
    `synchronized` actually would solve your problem, as would `volatile` or `AtomicInteger`. Thread-safety isn't only about race conditions. – shmosel Sep 23 '16 at 21:18
  • @shmosel, since when would it not constitute a race condition for one thread to perform an unsynchronized read of a variable that a different thread writes? But yes, any of the several synchronization mechanisms you enumerated would solve the problem. – John Bollinger Sep 23 '16 at 21:23
  • @JohnBollinger A race condition implies operations executing out of sequence. This code does't expect any particular sequence, just that the write will eventually be visible, which is not guaranteed. – shmosel Sep 23 '16 at 21:38
  • @shmosel non of these solved the problem. – Self Sep 23 '16 at 21:58
  • 1
    If you want more help, you'll have to fill out some of the gaps in your code. Who's creating and running your threads? Is there a variable called `getValue`? Who's instantiating `Parent`? Is someone supposed to call `Parent.getValue()`? Where is `GettingVaribale` declared? Why is `UpdatingVaribale` interrupting itself? – shmosel Sep 23 '16 at 22:04
  • Thanks for the comment. I accepted the answer below as an answer for a question like mine; however, it didn't work with me :). My two threads are created by two different `main()`, and they are in two different classes. When I call `setValue(2)`, I call `getValue()` and it returns `2`. But when I try to call `getValue()` by the second thread it returns `-1`. The reason why `UpdatingVaribale` is interrupting itself is because I don't need it anymore after setting the value. – Self Sep 24 '16 at 00:15

1 Answers1

2

There are some solutions here:

  1. use standard Java class AtomicInteger for storing your value in multi-threaded safe way. Actually it's the best and fastest way.
  2. add synchronized keyword to your getValue and setValue methods
  3. add volatile java keyword to i field definition

The source of your problem is i variable value actually looks different in different threads cause of CPU speed and memory optimization and you have to specify JVM somehow don't to do this optimization and - opposite - makes the latest i value visible in all threads.

UPDATE code for testing

public class SyncProblem {

    public static void main(String[] args) {
        Parent parent = new Parent();
        new Thread(parent.new GettingVaribale()).start();
        new Thread(parent.new UpdatingVaribale()).start();
    }
}

class Parent {
    private volatile int value = -1;

    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    class UpdatingVaribale implements Runnable {
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                setValue(2);
                Thread.currentThread().interrupt();
            }
        }
    }

    class GettingVaribale implements Runnable {
        @Override
        public void run() {
            while (getValue() == -1) {
                try {
                    System.out.println(getValue());
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
            System.out.println(getValue());
        }
    }
}
Andriy Kryvtsun
  • 3,220
  • 3
  • 27
  • 41
  • I've tried the three solutions. Non of them solved the problem. – Self Sep 23 '16 at 21:57
  • @Sultan as you code have a lot of syntax errors I fixed and put updated code in my answer update. You can simply copy-paste it in your IDE and run `main` method. The output is like `-1 2` before the program exit – Andriy Kryvtsun Sep 23 '16 at 22:14