The answer is given by the Java Language Specification §12.4.2:
Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A
might invoke a method of an unrelated class B
, which might in turn invoke a method of class A
. The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure. […]
Note the last sentence starting with “The implementation of the Java Virtual Machine is responsible for taking care …”
So you are not responsible for synchronization in the case of class initialization, and assigning initial values to static
variables is part of the class initialization, as specified in §8.3.2:
8.3.2. Field Initialization
If a declarator in a field declaration has a variable initializer, then the declarator has the semantics of an assignment (§15.26) to the declared variable.
If the declarator is for a class variable (that is, a static
field), then the following rules apply to its initializer:
…
- At run time, the initializer is evaluated and the assignment performed exactly once, when the class is initialized (§12.4.2).