0

I looked around and seemed similar code but mine is not working. My volatile variable is chaning in the class clock but my class vistor is not getting the changed variable. I will post my code. If theres a similar queston please link. Thank you for the help.

I tried by setting the declarations in all my classes for the volatile boolean variables to false. It didn't help.

public class Main {
volatile static boolean isInSession;
volatile static boolean sessionOver;

public static void main (String [] args)
{
    for (int i = 0; i < 25; i++) {
        Visitor visitor = new Visitor(i, isInSession);
        visitor.start();
    }
    Thread clock = new Thread(new Clock(isInSession, sessionOver));
    clock.start();

}



}



public class Visitor extends Thread {


volatile static boolean isInSession;
private int visitorId;
volatile static int seats = 5;

Visitor(int visotrId, boolean isInSession)
{
    this.isInSession = isInSession;
    setName("visitorId " + visitorId);

}
@Override
public void run() {

    while(true)
    {
        while(isInSession){}

        System.out.println("In visitor isInSession " + isInSession);

        if(isInSession)
            System.out.println("Visitor isInSession " + isInSession);

        try {
            Thread.currentThread().sleep(5000);
        }
        catch(InterruptedException e)
        { }

    }
}
public void msg(String m) {
System.out.println("["+(System.currentTimeMillis()-time)+"] 
"+getName()+": "+m);
}


}


public class Clock implements Runnable  {

volatile static boolean isInSession;
volatile static boolean sessionOver;
private int session = 0;

public Clock(boolean isInSession, boolean sessionOver)
{
    this.isInSession = isInSession;
    this.sessionOver = sessionOver;

}

@Override
public void run() {
    while(true)
    {
        try {
            Thread.currentThread().sleep(5000);
        } catch (InterruptedException e) {
        }
        isInSession = false;

        msg("Theater is open");

        try {
            Thread.currentThread().sleep(5000);
        } catch (InterruptedException e) {
        }

        isInSession = true;
        //System.out.println("In clock isInSession " + isInSession);


        session++;
    }
}// end of run

    public void msg(String m) {
    System.out.println("["+(System.currentTimeMillis()-time)+"]" +"Clock: 
    "+  m);
}

}
  • 4
    Arguments are passed by value in Java. Every object has its own boolean variable. Changing one will not magically change all the other. Just like in real life: every car has a color. If I paint a car in red, all cars don't magically become red. Not even those that were initially painted in the same factory, using the same color. – JB Nizet Apr 20 '19 at 05:58
  • Doesn't volatile mean I have one variable that's not cached in memory. How would you suggest going about it then with volatile variables. – Xavier Maldonado Apr 20 '19 at 06:17
  • 4
    It has absolutely nothing to do with volatile. Again: if you do `Car car1 = new Car("red"); Car car2 = new Car("red"); car1.setColor("green");`, then car1 will be green, and car2 wil still be red. They use two separate variables to hold their color, and changing one won't change the other. Whether you use volatile or multiple threads doesn't change anything to that: you have two separate variables. Your code has 3 separate `isInSession`variables, each with their own value: Main.isInSession, Visitor.isInSession, and Clock.isInSession. – JB Nizet Apr 20 '19 at 06:33
  • 1
    @XavierMaldonado, this thread will help you understand what is volatile used for, https://stackoverflow.com/questions/106591/what-is-the-volatile-keyword-useful-for. – darshgohel Apr 20 '19 at 06:35

1 Answers1

1

You can use AtomicBoolean for your purpose.

As JB Nizet has pointed out, arguments in Java are passed-by-value. Here's an answer on another SO post that explains this in detail.

For your purpose, it suffices to know that, "when we pass the value of an object, we are passing the reference to it" (a quote from the SO post mentioned above). By creating an AtomicBoolean object and passing it to both the Clock and Visitor objects, when Clock updates the value of the AtomicBoolean, the Visitor objects will receive the updated value too.

So, your main class should look like this:

public class Main {
    static AtomicBoolean isInSession = new AtomicBoolean(); // default value is false
    static AtomicBoolean sessionOver = new AtomicBoolean();

    public static void main (String [] args)
    {
        for (int i = 0; i < 25; i++) {
            Visitor visitor = new Visitor(i, isInSession);
            visitor.start();
        }
        Thread clock = new Thread(new Clock(isInSession, sessionOver));
        clock.start();
    }
}

To access the value of the AtomicBoolean in Visitor or to update the value in Clock, you can use the get() and set(boolean) method respectively.

Zhiyuan-Amos
  • 154
  • 2
  • 6