avatar

Coderek's blog

Loneliness is the gift of life

Thread safety when using Java static variables

In real world Java programming, it is always important to emphasize on thread safety.

Corrupt data occurs when multiple threads write and read the shared data in an uncontrolled fashion.

The key part is shared data.

Java's static keyword defines static memory allocation. This static memory, if handled incorrectly, can cause indeterministic errors.

For example in the following code, the static int in Host class is shared. Java will reuse it when a new object is created.

class Main {
  static class Host {
    private static int count = 0;
    void print() {
      System.out.println("count test: " + count );
    }
    void add() {
      count += 1;
    }
  }

  public static void main(String[] args) {
    Runnable a = () -> { 
      Host host1 = new Host();
      host1.add();
      host1.print();
    };

    for (int i=0;i<10;i++) {
      new Thread(a).start();
    }
  }  
}

The result is indeterministic with multiple threads. Rather than printing a sequence of numbers, it would print some seemingly random numbers.

This is because the read and write of the shared count in the threads can be interwined. Thus the value read by thread A might be a value before the previous thread did the update on the same variable.

The simple way to fix it is to synchronize the read/write access to the static count.

The extension of this example is static method. A static method must be used when it accesses some static variable that is defined outside the method. This means, it will also have the thread safety problem.

Sometimes the shared variable can be changed in a fashion that's not clearly visible. That they may not always use assignment to change the value. But it can be an object variable that by calling its method, the internal state is changed.

A typical example is SimpleDateFormat. We usually use it to parse the date string to some date object. In order to parse a date string, it has a parser built in. The parser keeps internal state. Thus, in order to make sure the state is not corrupt in multi-thread environment, access to the object must be synchronized. That's why we see the warning in the doc.

Synchronization

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

(End of article)