Normally in Java when concurrency is expected to be an issue either the synchronized
keyword would be used on methods that change or read the internal state of the object or a synchronized
block would be used with a lock on a non-null object. Both would require that accessor methods be created for setting the value of val1 and val2.
Example using synchronized on the methods that change (or read) internal state:
class ThreadSafe
{
private static int val1;
private static int val2;
static synchronized void go()
{
if (val2 != 0)
{
System.out.println(val1 / val2);
}
val2 = 0;
}
static synchronized void setVal1(int newVal1)
{
val1 = newVal1;
}
static synchronized void setVal2(int newVal2)
{
val2 = newVal2;
}
}
In this case because the methods are static, the synchronization will occur on the class itself.
Example using synchronization on a non-null object:
class ThreadSafe
{
private static int val1;
private static int val2;
private static Object lock = new Object();
static void go()
{
synchronized (lock)
{
if (val2 != 0)
{
System.out.println(val1 / val2);
}
val2 = 0;
}
}
static void setVal1(int newVal1)
{
synchronized (lock)
{
val1 = newVal1;
}
}
static synchronized void setVal2(int newVal2)
{
synchronized (lock)
{
val2 = newVal2;
}
}
}
See also What does 'synchronized' mean?