Vishvajeet Patil Vishvajeet Patil - 4 months ago 10
Java Question

Static Variable can not be set inside inner class

So I am having problem that I can not understand the reason why the static variable of other class set inside the inner class implementing the ActionListener is not visible in the main test file.

Below are the three files I am having problem with.The expected action of changing static variable flag in Verification class should terminate the program but it doesn't.

InnerClassTest File(Main class file)

package innerClass;

public class InnerClassTest
{
public static void main(String[] args)
{
TalkingClock clock = new TalkingClock(2000, true);
clock.start();
while(true)
{
if(Verification.flag == true)
{
System.exit(0);
}
if (TalkingClock.flag == true)
{
System.exit(0);
}
}
}
}



TalkingClock File

package innerClass;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.Timer;

public class TalkingClock
{
private int interval;
private boolean beep;
public static boolean flag = false;
public TalkingClock(int interval, boolean beep)
{
this.interval = interval;
this.beep = beep;
}

public void start()
{
ActionListener listener = new TimePrinter();
Timer t = new Timer(interval, listener);
t.start();
}

public class TimePrinter implements ActionListener
{
@Override
public void actionPerformed(ActionEvent event)
{
Date now = new Date();
System.out.println("At the tone, the time is " + now);
if (beep) Toolkit.getDefaultToolkit().beep();
Verification.flag = true;
flag = true;
}
}
}


Verification Class File

package innerClass;

public class Verification
{
public static int count = 0;
public static boolean flag = false;
}

Answer

This is because of multithreading issues, not inner classes or static variables.

You are accessing/modifying flag from multiple different threads, but not telling the compiler that it needs to ensure that the value is being correctly updated to reflect changes on other threads.

From the JLS section 8.3.1.4:

The Java programming language allows threads to access shared variables (ยง17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.

The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable

Without that keyword, the JVM and compiler are free to make optimizations which don't allow for changes by other threads. Make flag volatile and the problem will be fixed.