A thread que primeiro se refere a uma classe deve inicializá-la. Por exemplo, considere esta interface:
interface Constantes { int[] IARRAY = { 42 }; }
A thread que se referir primeiro a esta interface irá inicializá-la;
entre outras coisas, esta tarefa inclui criar um vetor com um elemento inteiro,
atribuir o valor 42 a este elemento e armazenar a referência ao vetor na
variável IARRAY
.
Agora, veja a classe seguinte (que utiliza a interface
Constantes
):
class Foo implements Runnable { public static void main(String[] args) { Foo f = new Foo(); Thread t1 = new Thread(f), t2 = new Thread(f); t1.start(); t2.start(); } public void run() { System.out.println(Constants.IARRAY[0]); } }
Suponha que t1
seja a primeira thread que alcança a linha onde
o valor de IARRAY[0]
é exibido. Então, t1
precisa
inicializar a interface Constantes
e, de acordo com as regras de
Java, se t2
também atingir esta linha, deve esperar até que a
inicialização tenha se completado (ou seja, Java não permite que t2
inicialize a interface Constantes
se outra thread já está fazendo
o mesmo, nem permite que t2
veja o valor de IARRAY[0]
enquanto a inicialização não acabar).
Um problema com o algoritmo Dinning-Schonberg é que ele não leva
em conta essa regra da linguagem Java, e, para um código como no exemplo acima,
o algoritmo pode emitir alarmes sobre condições de disputa que de fato não
existem. Para prevenir estes alarmes falsos, você pode selecionar a opção
Ignorar inicialização de classes. Por outro lado, condições de
disputa verdadeiras (como no exemplo a seguir, envolvendo a variável
Main.pi
), serão perdidas se essa opção estiver selecionada:
interface Y { float PI = Main.pi; } class Main { static float pi = 2.14; public static void main(String[] args) { new Thread() { public void run() { System.out.println(Y.PI); // pode imprimir 2.14 ou 3.14 } } Main.pi++; } }A opção para ignorar a inicialização de classes não faz sentido com Eraser (que automaticamente ignora a inicialização de variáveis, em particular durante a inicialicação de classes), mas note que Eraser pode perder uma condição de disputa como a mostrada no exemplo anterior.